Gorilla schema fails silently? I must be doing something wrong here.

477 views
Skip to first unread message

maxpow...@gmail.com

unread,
Jan 12, 2015, 12:00:19 AM1/12/15
to golan...@googlegroups.com
As part of my ongoing quest to create a JSON CRUD service I decided that it would be a good idea to validate user input because frankly I would have to be insane not to.

The most direct method of doing this in other languages has been to marshall the user input into the language's equivalent data structure.
So for Go that means structs, and by all accounts the marshalling should be the Gorilla Schema package.

Except it's not working and frankly I'm not at all sure why.

Here is what I've got for a simple user registration form...

Given that I am testing with...

 curl -i -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "email=ima...@go.lang&password=changeme&created=now" http://mysite.com:8080/api/register



And my code looks like

import(
   
...
     
"github.com/gorilla/schema"
)


type
User struct{
    email      
string
    password    
string
    created    
string
}



var decoder = schema.NewDecoder()  //This global courtesy of advice from http://www.gorillatoolkit.org/pkg/schema

func main
(){
r
:= mux.NewRouter()
    r
.HandleFunc("/", statusHandler)
    r
.HandleFunc("/env", envHandler)
    r
.HandleFunc("/register", registrationHandler)
   
    http
.Handle("/", r)

    bind
:= fmt.Sprintf("%s:%s", os.Getenv("HOST"), os.Getenv("PORT"))
    log
.Printf("listening on %s...", bind)
       
    err
:= http.ListenAndServe(bind, nil)
   
if err != nil {
        panic
(err)
   
}
}

/**
* CORS allow all
*/

func allowOriginAll
(w http.ResponseWriter){
    w
.Header().Set("Access-Control-Allow-Origin", "*")
}

/**
* Handles registration, responds with one of
* "OK", or
*  an error code indicating either missing or duplicated information
*/

func registrationHandler
(w http.ResponseWriter, r *http.Request){
    allowOriginAll
(w);
   
    err
:= r.ParseMultipartForm(2048)
   
if err != nil {
        http
.Error(w, "Invalid or missing fields", http.StatusBadRequest)
       
return;
   
}

    log
.Printf("registrationHandler: %+v\n",r.PostForm)
    user
:= new(User)

   
// r.PostForm is a map of our POST form values
    err
= decoder.Decode(user, r.PostForm)

   
if err != nil {
        log
.Printf("Error: %+v\n",err)
        http
.Error(w, "Error Invalid or Missing Params", http.StatusBadRequest)
       
return;
   
}
   
     fmt
.Fprintf(w,"%+v\n",user);
     log
.Printf("%+v\n",user);
     
     log
.Printf("Email is %s",user.email);
   
//Setting this as a session cookie so we don't have to parameterize it.
    session
, _ := store.Get(r, "user")
    session
.Values["user"] = user
    session
.Save(r, w)
   
   
   
//We now have a user object with an email and a password
   
//Query the users collection to determine if there is a user with that email already  
       
}




In my output log I see the following...
2015/01/12 04:39:50 registrationHandler: map[email:[imanoob@go.lang] password:[changeme] created:[now]]
2015/01/12 04:39:50 &{email: password: created:}
2015/01/12 04:39:50 Email is

In the terminal where I call curl I just get...
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Date: Mon, 12 Jan 2015 04:39:50 GMT
Content-Length: 29
Content-Type: text/plain; charset=utf-8

&{email: password: created:}



At this point I've been troubleshooting for about the last 5 hours with no luck.
I'm really hoping someone has an idea or sees something obvious I've missed.
Otherwise I'll have to go back to isolating each field individually using FormValue or something, but I hate that idea for a myriad of reasons. 

I'm kind of fond of the validate input by contract idea and importing directly to an object/struct and complaining if it fails.
Not really sure if that's idiomatic in go or not though.

Thanks!




John Clover

unread,
Jan 12, 2015, 12:33:21 AM1/12/15
to maxpow...@gmail.com, golan...@googlegroups.com
I'm not super familiar with this, but doesn't schema require that the struct have exported fields (capitalized names)

You can get around that by capitalizing the names, and then giving them a tag like in the example here: http://www.gorillatoolkit.org/pkg/schema

So
type User struct{
Email string `schema:"email"`
Password string `schema:"password"`
Created string `schema:"created"`
> 2015/01/12 04:39:50 registrationHandler: map[email:[ima...@go.lang] password:[changeme] created:[now]]
> 2015/01/12 04:39:50 &{email: password: created:}
> 2015/01/12 04:39:50 Email is
>
> In the terminal where I call curl I just get...
> HTTP/1.1 200 OK
> Access-Control-Allow-Origin: *
> Date: Mon, 12 Jan 2015 04:39:50 GMT
> Content-Length: 29
> Content-Type: text/plain; charset=utf-8
>
> &{email: password: created:}
>
>
>
> At this point I've been troubleshooting for about the last 5 hours with no luck.
> I'm really hoping someone has an idea or sees something obvious I've missed.
> Otherwise I'll have to go back to isolating each field individually using FormValue or something, but I hate that idea for a myriad of reasons.
>
> I'm kind of fond of the validate input by contract idea and importing directly to an object/struct and complaining if it fails.
> Not really sure if that's idiomatic in go or not though.
>
> Thanks!
>
>
>
>
>
> --
> You received this message because you are subscribed to the Google Groups "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

maxpow...@gmail.com

unread,
Jan 12, 2015, 1:08:45 AM1/12/15
to golan...@googlegroups.com, maxpow...@gmail.com, jo...@jclo.co
Yes that did indeed fix it.  Thank you, works perfectly now.
Reply all
Reply to author
Forward
0 new messages