Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

form post, bind to pointer in struct failed #893

Closed
cch123 opened this issue Apr 20, 2017 · 8 comments
Closed

form post, bind to pointer in struct failed #893

cch123 opened this issue Apr 20, 2017 · 8 comments

Comments

@cch123
Copy link

cch123 commented Apr 20, 2017

complete demo code is

package main

import (
	"fmt"
	"log"
	"net/http"

	"github.com/gin-gonic/gin/binding"
)

type person struct {
	X *int `json:"x" form:"x" binding:"required"`
}

func contentType(r *http.Request) string {
	return filterFlags(requestHeader(r, "Content-Type"))
}

func filterFlags(content string) string {
	for i, char := range content {
		if char == ' ' || char == ';' {
			return content[:i]
		}
	}
	return content
}

func requestHeader(r *http.Request, key string) string {
	if values, ok := r.Header[key]; ok {
		return values[0]
	}
	return ""
}

func bind(r *http.Request, dst interface{}) error {
	contentType := contentType(r)
	if len(contentType) == 0 {
		// do some thing?
	}
	fmt.Println(contentType)

	b := binding.Default(r.Method, contentType)
	return b.Bind(r, dst)
}

func sayhello(wr http.ResponseWriter, r *http.Request) {
	p := person{}
	err := bind(r, &p)
	fmt.Printf("%#v\n", p)
	fmt.Println(err)
}

func main() {
	http.HandleFunc("/", sayhello)
	err := http.ListenAndServe(":9090", nil)
	if err != nil {
		log.Fatal("ListenAndServe:", err)
	}
}

I've already updated the validator to v9.

Is there any plan to support pointer kind binding?

@cch123 cch123 changed the title form post bind to pointer in struct failed form post, bind to pointer in struct failed Apr 20, 2017
@deankarn
Copy link

Can you provide an example of the value you posted and the output you got?

I can say for 100% certainty that validator supports pointers.

@cch123
Copy link
Author

cch123 commented Apr 24, 2017

@joeybloggs , thx for your reply, but I think this is not the validator's fault. Below is an example reproduce the case. I said using validator.v9 was to clarify that the required tag is correct...

use httpie to post a form,

~ ❯❯❯ http --verbose --form post localhost:9090 x=1
POST / HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 3
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Host: localhost:9090
User-Agent: HTTPie/0.9.3

x=1

HTTP/1.1 200 OK
Content-Length: 0
Content-Type: text/plain; charset=utf-8
Date: Mon, 24 Apr 2017 02:42:11 GMT

get the following error

application/x-www-form-urlencoded
main.person{X:(*int)(nil)}
Unknown type => here

Unknown type is reported by gin/binding/form_mapping.go

func setWithProperType(valueKind reflect.Kind, val string, structField reflect.Value) error {
	switch valueKind {
	case reflect.Int:
		return setIntField(val, 0, structField)
------------
.....skiped...
------------
	default:
		return errors.New("Unknown type") // here
	}
	return nil
}

Because the valueKind is reflect.Ptr.

@deankarn
Copy link

I see @cch123

I don't know if the gin team has plans to add support, but if you or the gin team is interested in adding I also have a library that will handle just about anything you can throw at it https://github.com/go-playground/form.

I propose that the form decoding is made a configurable interface, just like validator, to allow for plugging in different or more robust libraries.

\cc @javierprovecho @appleboy

@thinkerou
Copy link
Member

@cch123 I run your code using the command go run main.go and it output the following info:

main.person{X:(*int)(nil)}
Key: 'person.X' Error:Field validation for 'X' failed on the 'required' tag

main.person{X:(*int)(nil)}
Key: 'person.X' Error:Field validation for 'X' failed on the 'required' tag

@joeybloggs I used validator.v9.

@cch123
Copy link
Author

cch123 commented Jul 13, 2017

@thinkerou , gin's original form binding(not the binding tag, here the binding uses the tag "form" in the struct field tags) does not support mapping form request data to pointer type field of a struct, you can find the form decode part of gin's binding package to confirm that.

So even if you update the validator to v9, 'required' validation (here the validation uses the 'binding' tag of the struct, because gin changes the validator's default tag name) of the pointer type field in struct will still fail.

@deankarn
Copy link

I did propose a potential solution #893 (comment) if anyone on the Gin team is interested.

@javierprovecho
Copy link
Member

javierprovecho commented Jul 17, 2017

@joeybloggs yes, i'll review it in one/two days, I need to close other issues first, thanks! 😃

@thinkerou
Copy link
Member

Implement in #1336 . try it in the latest master branch. right?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants