Golang AJAX calls not passing information.

1,338 views
Skip to first unread message

llewyn lew

unread,
Oct 27, 2015, 12:10:56 PM10/27/15
to golang-nuts
This is a snippet of an ajax call I am sending.
It sends name, email, and password.

$(document).ready(function () {
    $('#register').click(function(e) {
e.preventDefault();
$.ajax({
type: 'POST',
url: 'http://localhost:8080/ajax-register',
contentType: 'application/json; charset=utf-8',
data:
{
null:false,
"name":"name",
"email":"email",
"password":"password"
}


func RegisterHandler(w http.ResponseWriter, r *http.Request) {

type User struct {
Name string `json:"name"`
Email string `json:"email"`
Password string `json:"password"`
}
if r.Method == "POST" {
//decoding http request
decoder := json.NewDecoder(r.Body)

u := User{ }

// Decoder stores the parsed JSON into our user struct
// fails on regular submit, pass on REST client submit.
err := decoder.Decode(&u)
if err != nil {
log.Fatalln(err)
}

      fmt.Println(u.Email)
fmt.Println(u.Name)
fmt.Println(u.Password)


1. Why does Golang require a null field in the data being passed in AJAX. An error occurs if I comment the field out.

invalid character 'a' in literal null (expecting 'u') // This is because it is looking for null. I have "name".



2. The outputs from the last 3 lines return nothing, how can I check if r.Body or decoder contains the name,email,password fields passed from the AJAX call?


 

Konstantin Khomoutov

unread,
Oct 27, 2015, 1:52:22 PM10/27/15
to llewyn lew, golang-nuts
On Tue, 27 Oct 2015 09:10:55 -0700 (PDT)
llewyn lew <llewy...@gmail.com> wrote:

> This is a snippet of an ajax call I am sending.
[...]
It doesn't -- you have an error in your code somewhere.
See below.

> 2. The outputs from the last 3 lines return nothing, how can I check
> if r.Body or decoder contains the name,email,password fields passed
> from the AJAX call?

As usually, it helps breaking the problem down to the pieces which can
be debugged separate.

First, let's deal with JSON decoding.
Instead of fighting with decoding essentially unknown data -- you can't
tell for sure what exactly your jQuery sent to your server -- you
should just check JSON decoding in a controlled environment.
A simple example shows that JSON decoding works just OK: [1].

Since JSON decoding works OK, there must be something bad with the
request your AJAX is making.

There are multiple approaches to verify it.

First, you can use browser debugging tools: recent versions of Firefox
and Chrome are able to show you what's going in and out in the payloads
of requests done through AJAX.

The second approach is to temporarily write the request's body to a
file in your HTTP handler, and inspect it afterwards.
Something like this:

if r.Method == "POST" {
f, err := os.OpenFile("/tmp/blah",
os.O_CREATE | os.O_WRONLY | os.O_TRUNC, 0666)
defer f.Close()
if err != nil { ... }
io.Copy(f, r.Body)
}

Then do your request, then inspect what's there in "/tmp/blah".

The third approach is to fire up some network packet capturing program
(say, Wireshark) and sniff on the network traffic -- again, inspecting
what your browser sends. This won't work for SSL/TLS-enabled servers
(well, it's still possible to decode the traffic but requires too much
effort).

My guess on the root cause of your issue is that your AJAX actually
formats the payload of your POST request according to the
multipart/form rules -- no matter you provide a sensible value
for the Content-Type header, and set the request's object "data" member
to something which looks like JSON (and it's not JSON, it's a
JavaScript object).

[2] details how to force jQuery's AJAX wrapper to really post JSON,
and here's the helper I'm using in my own code to do that:

function postJSON (url, data) {
return $.ajax({
type: 'POST',
url: url,
contentType: 'application/json; charset=UTF-8',
data: ko.toJSON(data),
processData: false
});
};

(The ko.toJSON() function is a part of the Knockout JS framework; you
might use something built into the browser or provided by jQuery to
serialize your data to a JSON string.)

1. http://play.golang.org/p/d-2ORhIT_A
2. http://benjamin-schweizer.de/jquerypostjson.html

Konstantin Khomoutov

unread,
Oct 27, 2015, 2:19:21 PM10/27/15
to Konstantin Khomoutov, llewyn lew, golang-nuts
On Tue, 27 Oct 2015 20:51:57 +0300
Konstantin Khomoutov <flat...@users.sourceforge.net> wrote:

[...]
> > $.ajax({
> > type: 'POST',
> > url: 'http://localhost:8080/ajax-register',
> > contentType: 'application/json; charset=utf-8',
> > data:
> > {
> > null:false,
> > "name":"name",
> > "email":"email",
> > "password":"password"
> > }
[...]
> My guess on the root cause of your issue is that your AJAX actually
> formats the payload of your POST request according to the
> multipart/form rules -- no matter you provide a sensible value
> for the Content-Type header, and set the request's object "data"
> member to something which looks like JSON (and it's not JSON, it's a
> JavaScript object).
>
> [2] details how to force jQuery's AJAX wrapper to really post JSON,
> and here's the helper I'm using in my own code to do that:
>
> function postJSON (url, data) {
> return $.ajax({
> type: 'POST',
> url: url,
> contentType: 'application/json; charset=UTF-8',
> data: ko.toJSON(data),
> processData: false
> });
> };
>
> (The ko.toJSON() function is a part of the Knockout JS framework; you
> might use something built into the browser or provided by jQuery to
> serialize your data to a JSON string.)
[...]
> 2. http://benjamin-schweizer.de/jquerypostjson.html

To elaborate more on this, [3] states:

| processData (default: true)
| Type: Boolean
| By default, data passed in to the data option as an object
| (technically, anything other than a string) will be processed and
| transformed into a query string, fitting to the default content-type
| "application/x-www-form-urlencoded". If you want to send a
| DOMDocument, or other non-processed data, set this option to false.

So basically to make jQuery's AJAX wrapper actually send JSON you either
must set the "data" member to a string, not JS object or set the
"processData" member to false. I'm doing both for the call to look
the most sensible way possible.

3. http://api.jquery.com/jquery.ajax/

llewyn lew

unread,
Oct 27, 2015, 3:15:58 PM10/27/15
to golang-nuts, flat...@users.sourceforge.net, llewy...@gmail.com
Thanks so much Konstantin, your solutions pointed me in the right direction.

I initially thought this was something wrong on golang's end, but realized that the JSON passed wasn't particularly correct.

It was initially passing as {name: "name", value: "john"}{name: "email", value: "john"} etc.

So it was indeed my JSON formatting.

var formData = JSON.stringify($('#register-form').serializeObject());
I replaced my formdata with proper formatting and golang properly parses the JSON and decodes it. The lookup for null really had me going in circles.

The kicker was your ko.toJSON which clicked!
Reply all
Reply to author
Forward
0 new messages