Giter Site home page Giter Site logo

binding's People

Contributors

3xx0 avatar attilaolah avatar beatrichartz avatar codegangsta avatar danawoodman avatar etix avatar ghostiam avatar jakejscott avatar leeor avatar mholt avatar modgravert avatar p-lewis avatar rday avatar robgssp avatar sneakyness avatar titanous avatar tomsteele avatar tpng avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

binding's Issues

Error when binding structs with dates

I've just had a problem while trying to bind a struct with some dates on it like this

{"birthDate":"2015-02-19T00:00:00", "name": "name", "place": "Málaga"}

It evens doesn't show me any error... It just doesn't bind any data.

Anyone on this?

My file upload isn't working?

Am trying to use the README's example of a simple form with a file in it.

type UploadForm struct {
    Title       string                `form:"title"`
    Description string                `form:"description"`
    FileUpload  *multipart.FileHeader `form:"fileUpload"`
}

and then the service routine...

    m.Post("/upload", binding.MultipartForm(UploadForm{}), uploadHandler(uf UploadForm, r render.Render) {
        log.Println("Upload Form: ", uf)
        s := fmt.Sprintf("Posted an Upload: %v / %v \n", uf.Title, uf.Description)
        r.HTML(200, "upload_success", s)
    })

but uf, the form struct is always Nil.

Any ideas? Any ideas on how to fix?

binding.Form don't show any errors

func mapForm(formStruct reflect.Value, form map[string][]string,
formfile map[string][]*multipart.FileHeader, errors Errors)

the last param is not a pointer,so if has errors,it don't get work

Binding “cannot return value obtained from unexported field or method”

I have the following route:

m.Post("/users", binding.Bind(models.User{}), func(user models.User, r render.Render)

And I receive the following error message when I try to do a Post request:

"PANIC: reflect.Value.Interface: cannot return value obtained from unexported field or method"

My model is:

type User struct {
    id         int
    UUID       string    `json:"uuid"`
    Username   string    `json:"userName" form:"userName" binding:"required"`
    Firstname  string    `json:"firstName" form:"Firstname" binding:"required`
    Lastname   string    `json:"lastName" form:"Lastname" binding:"required`
    Email      string    `json:"email" form:"Email" binding:"required`
    IsActive   bool      `json:"isActive"`
    DateJoined time.Time `json:"dateJoined"`
}

Sorry. The problem was the attribute "id". If I set this as "Id" works perfectly or if I set the tag form:"-" too.

Thank you and sorry for the question. You can delete it.

suggestion: allow preprocessing of params

allow preprocessing of params (before validation)
via e.g. Preprocess (binding.Preprocess)

use cases:
remove leading zeros
remove spaces

before putting data into a struct
before validating data

Preprocess might receive
req.Form
use "Set(key, value string)" to modify value

not sure whether to make a copy of req.Form or just modify it

Support of embeded *Struct for form binding

type Embed struct {
    Test string `form:"test" binding:"required"`
}

type Outer struct {
    *Embed
}

Currently, if I bind to Outer{}, *Embed is nil after binding even if I pass the "test" parameter in the request.

External Use of binding errors struct

I'm using martini and the binding package with Angular.

So if a requests fails the validation Angular gets back a binding.Errors() object which is all good.

What I'd like to do is to reuse the same error structure for other errors that might arise in the app basically so that I can have a consistent error checking experience with Angular. Say if the if I need to say a DB error occurred or something.

I'm currently doing this as Errors is exported, I just wanted to check my approach and wonder if we could formalise it or something so I don't feel so hacky.

Any thoughts?

Thanks

Allow form-urlencoded POST/PUT data with a size over 10MB

Currently the POST/PUT size is limited by the parseForm function in the http package (see https://golang.org/src/net/http/request.go#L834). However, the mulitform parser has a configurable limit (with MaxMemory), so why not apply this to the form-urlencoded requests too?

I'd really like to configure my own limit (we use Mandrill incoming webhooks, and sometimes the incoming data is larger than 10MB, Mandrill only supports application/x-www-form-urlencoded.

This possible resutlts in some code copy/pasting from the http package.

Binding to params

Was thinking it would be cool if binding could bind to martini params. If this is something you guys think would be cool I will try and find some time to hack it up.

Multiple bindings, validation errors chains.

example:

router.Post(
        "/user/stream",
        binding.Json(StreamRequest{}),
        binding.Form(APICredentials{}),
        AuthenticationMiddleware,
        postUserStreamHandler,
 )

there is no errors in postUserStreamHandler but if i change the order, its fine.
Validation errors should chain or smth.

Do binding to route and URL values

I think having type safe route values at least would really be an improvement

I hope I haven't overlooked anything though...

It could work with the struct tag "route:" or in the case of URL values "url:"

Pointers to basic types do not deserialize correctly

If you have a basic type that's a pointer, deserialization doesn't happen correctly. For instance:

type Post struct {
    Id      uint64
    Content *string
}

causes a panic during the ValidateStruct step. The validation incorrectly assumes if it's a pointer, it's a pointer to a struct.

A full, stand alone test would be the following

package main

import (
    "log"

    "github.com/go-martini/martini"
    "github.com/martini-contrib/binding"
)

type Post struct {
    Id      uint64
    Content *string
}

func main() {
    c := martini.Classic()
    c.Post("/", binding.Json(Post{}), func(p Post) {
        log.Println(p)
    })
    c.Run()
}

With a curl test of

curl -XPOST --data '{"content": "fubar"}' http://localhost:3000/
$GOROOT/src/pkg/reflect/type.go:654 (0x48a9cd)
        (*rtype).NumField: panic("reflect: NumField of non-struct type")
$GOPATH/src/github.com/martini-contrib/binding/binding.go:191 (0x432512)
        validateStruct: for i := 0; i < typ.NumField(); i++ {
$GOPATH/src/github.com/martini-contrib/binding/binding.go:171 (0x43372a)
        func.005: errors = validateStruct(errors, obj)

I've also done a quick JSON test case with the following commit: losinggeneration@58a8515

Support for nested arrays with structs

Thanks for the great work you've done with martini and its companions like binding! :)

Now to the issue...It seems that it isn't possible to have a nested array of some own structs (yes, I saw no tests for it either) like so:

type Foo struct {
  Bars []Bar
}

type Bar struct {
  A string `form:"a"`
  B string `form:"b"`
}

Binding Foo with the above will not work and it ignores the form fields a and b even if they are passed in. Removing the [] and just having a single copy works fine (as you also have in the tests).

Before I start sending a PR I'd like to see what makes sense to do here.

Does it make sense to have an array of structs? I think so. Imagine having a form with a dynamic part where one can add zero or more of some set of fields. It would make sense to have a struct to represent those, and bang!, we have this very problem.

How would that look like on the form side to start with? I see that an array of strings for instance just takes all fields with the name and sticks them into the array. The implication of this is that it's not possible to have different fields with the same name. Would the same principle be a good approach now as well?

I'd like to hear what you guys who have worked on this a longer time have to say. What do you think is a good way to support what I ask for or is it even something you think makes sense to support?

Thanks!

Should the Errors struct provide getters and setters?

As I re-write the tests, I'm finding a few more edge cases and issues. For instance, if you have a simple struct:

type Post struct {
    Title   string `form:"title" binding:"required"`
    Content string `form:"content"`
}

Notice the Title field is required. However, suppose your struct is also a Validator, and its Validate() method looked like:

func (p Post) Validate(errs *Errors, req *http.Request) {
    if len(p.Title) < 10 {
        errs.Fields["title"] = "Title is too short"
    }
}

Now suppose a request comes in and the Title field is left blank. Well, the obvious error to get back is simply "Required" -- who cares that it's too short, it didn't even get submitted!

Turns out that, right now, this implementation will overwrite the "Required" error which is added for you.

So should the Fields and Overall fields of the Errors struct be made un-exported, and used with getters and setters instead? (The setter could prevent overwriting an existing error for that field.)

And should we allow multiple errors to the same key (i.e. instead of map[string]string, we have map[string][]string)? That would allow us to show both errors for the field... or however many... the downside is that it's slightly more complex.

See issue #3 for a similar discussion (though I'm not sure I want to include original input value, as that is even more complex).

Thoughts?

Validation fails for Types with unexported fields

For Json Posts I have the following Type:

type Host struct {
    Id         string    `json:"id,omitempty" gorethink:"id,omitempty"`
    Name       string    `json:"name" gorethink:"name" binding:"required"`
    Errors     bool      `json:"errors" gorethink:"errors" binding:"required"`
    Updated    time.Time `json:"updated" gorethink:"updated"`
}

The binding works perfectly. But when I set for the time.Time struct the required field tag with binding:"required I a get a panic:

type Host struct {
    Id         string    `json:"id,omitempty" gorethink:"id,omitempty"`
    Name       string    `json:"name" gorethink:"name" binding:"required"`
    Errors     bool      `json:"errors" gorethink:"errors" binding:"required"`
    Updated    time.Time `json:"updated" gorethink:"updated" binding:"required"`
}

This line is the problem:

        if strings.Index(field.Tag.Get("binding"), "required") > -1 {
            if field.Type.Kind() == reflect.Struct {
                validateStruct(errors, fieldValue) //<- THIS LINE PANICS
            } else if reflect.DeepEqual(zero, fieldValue) {
                errors.Fields[field.Name] = RequireError
            }
        }

I know the what the problem is, but not really a good, general way to solve this. The problem is that the time.Time struct does have no exported fields, just methods:

type Time struct {
     // sec gives the number of seconds elapsed since
     // January 1, year 1 00:00:00 UTC.
     sec int64

     // nsec specifies a non-negative nanosecond
     // offset within the second named by Seconds.
     // It must be in the range [0, 999999999].
     //
     // It is declared as uintptr instead of int32 or uint32
     // to avoid garbage collector aliasing in the case where
     // on a 64-bit system the int32 or uint32 field is written
     // over the low half of a pointer, creating another pointer.
     // TODO(rsc): When the garbage collector is completely
     // precise, change back to int32.
     nsec uintptr

     // loc specifies the Location that should be used to
     // determine the minute, hour, month, day, and year
     // that correspond to this Time.
     // Only the zero Time has a nil Location.
     // In that case it is interpreted to mean UTC.
     loc *Location
 }

And then the following line of code does not work:

fieldValue := val.Field(i).Interface()

Maybe someone has a good idea how to fix this.

Bind() should guess deserialization method without reading body

tl;dr If a request comes in without a Content-Type, what do we do?

When the Bind() method is looking at the request to see which deserialization method to use, there is, I think, a bug if the "else" block is entered... suppose JSON was POSTed without a Content-Type. That "else" block is entered and, first, a JSON deserialization is attempted. If there are any errors, it uses form deserialization.

Two problems:

  1. The JSON deserializer reads the body, so the stream is empty if and when the form deserializer tries to read it
  2. The JSON deserializer may succeed, even if the Validation middleware later adds errors to the context (for example: "cannot be a negative number" for one of the fields...), so form deserialization proceeds when it should not, because there is at least one error on the context.

I'm willing to submit a fix for these, but would like some feedback first. How do we guess the Content-Type correctly and elegantly? Peek at the first character of the request body for a [ or { character to detect JSON? That seems kind of unreliable.

Thoughts?

binding bug

when struct has a struct field, it will miss values

Cleanup, verify tests

The tests are getting a bit unwieldy and should probably be separated into more files. Also, each test should be reviewed for effectiveness; for example, tests for empty payloads might need some revising to actually test what we think they're testing.

I've started splicing the tests out into separate files and cleaning them up. Many are being rewritten as I verify that they test what we think they're testing, and more test cases will be added. (Thank you, GoConvey, for the in-editor notifications of test results!)

Current progress is in the tests branch of this repository.

binding.Bind failed to bind query params from GET without content-type header

package main

import "github.com/go-martini/martini"
import "github.com/martini-contrib/binding"

type TestStruct struct {
  Test string `form:"test"`
}

func test(t TestStruct) {

}

func main() {
  m := martini.Classic()
  // need to bind with binding.Form instead to work
  m.Get("/", binding.Bind(TestStruct{}), test)
  m.Run()
}

The case where the request is a GET with query parameters without specifying Content-Type header, the binding will fail in the form of PANIC: Value not found for type TestStruct.
Need to call binding.Form explicitly in this case.

Map a pointer of a struct to an interface

I want to map a pointer of a struct to a specific interface, but I can't. I read codegangsta/martini-contrib#34 (comment) and I see the current limitation is introduced to avoid race conditions.

But I think this limitation is not necessary, for example, after changing line 402 of binding.go

context.MapTo(obj.Elem().Interface(), ifacePtr[0])

to

context.MapTo(obj.Interface(), ifacePtr[0])

it still works (although it requires a struct to implement the interface methods with a pointer receiver). Because that obj is created by reflect.New each time a request comes in, there are no race conditions.

Additional binding tags and validation features

After coming from .NET MVC, I am accustom to model binding. However, there were many more validation rules you could set on the model fields.

For example, now you have

 type BlogPost struct {
    Title   string    `form:"title" json:"title" binding:"required"`
}

And you have the "Binding:required", which will add an error if its not there. Is there any chance you'd consider adding some other validation tags, like for example, marking a field as an email? There are some other really common ones too, like credit card, date, minlength, maxlength etc. Sure you could just add your own validator, but it would be nice to be able to add these to the model and have that taken care of for you:

type BlogPost struct {
        Title   string    `form:"title" json:"title" binding:"required" minlength:"10"`
        Email   string    `form:"title" json:"title" binding:"required" email:"true"`
 }

The syntax above is just an example, not necessarily how I would do it. Is this something that might belong here?

Errors should include the original value as well

Just a thought, but to make Form validation more useful, the errors should probably include the original value as well. It seems like it'd be simpler to model forms with all of the information coming from one place. I can implement, but I'm curious on everyone's thoughts first.

Error with binding false `bool` values and binding:"required"

type ThisObj struct {
    ID         string       `json:"id"`
    Name       string       `json:"name" binding:"required"`
    Online     bool         `json:"online" binding:"required"`
}

In the above example, bind gives me a RequiredErrorwhen I POST the following JSON string:

{
    "name": "test",
    "online": false
}

However, when I set online to 'true' in the above JSON string, binding works fine. I assume this is a bug as a false value should still fulfill the required tag?

Missing values and media type errors

from @abh

With the code below I get [martini] PANIC: Value not found for type *main.checkForm if I run curl -XPOST -dqueue=1 http://localhost:1234/check/127.0.0.1 and if I run the same without any form parameters I get a 400 bad request response and this JSON in the response {"overall":{"DeserializationError":"mime: no media type"},"fields":{}}.

Neither is what I expected. I was using roughly the same code with the now removed form middleware.

type checkForm struct {
    Queue string `form:"queue"`
}

func runWeb() {
    m := martini.Classic()
    m.Use(render.Renderer())

    m.Post("/check/:ip",
        binding.Bind(checkForm{}),
        func(res http.ResponseWriter, params martini.Params, options *checkForm, rndr render.Render) {
                   ....

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.