Bussiere
Bussiere

Reputation: 1144

How to receive a jsonp request in golang

I send some data using jquery in the jsonp format :

console.log(data.location.lng);
console.log(data.location.lat);
console.log(data.accuracy);
var urlgr = "http://127.0.0.1:9220/geo/rec_geo/";
var pfg = {
    //lo: data.location.lng,
    lo: 1.0,
    //la: data.location.lat,
    la: 2.0,
    //ac: data.accuracy,
    ac: 3,
};
$.ajax({
    type: 'GET',
    url: urlgr,
    crossDomain: true,
    data: JSON.stringify(pfg),
    dataType: 'jsonp',
    contentType: "application/json; charset=utf-8",
    success: function (data) {
        console.log("data rec geo");
        console.log(data);

    }
});

here is my code in golang to receive it :

type geoData struct {
    Long float32 `json:"lo"`
    Lat   float32  `json:"la"`
    Accuracy  int `json:"ac"`
}

func recordGeo(w http.ResponseWriter, r *http.Request) {
    s := strings.Split(r.RemoteAddr, ":")
    ip := s[0]
    Info.Println("4")
    var geoRec geoData
    decoder := json.NewDecoder(r.Body)
    err := decoder.Decode(&geoRec)
    fmt.Println("geoRec")
    fmt.Println(geoRec)
    checkErr(err)
}

but i have a EOF error :

2017/07/01 07:16:22 http: panic serving 127.0.0.1:50680: EOF

So my question is how to properly receive a jsonp request in golang and parse it to a struct ?

here is the request that i get in the golang server side :

GET /geo/rec_geo/?callback=jQuery31108538596418163691_1498913991164&{%22lo%22:1,%22la%22:2,%22ac%22:3}&_=1498913991166 HTTP/1.1
Host: 127.0.0.1:9220
user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
accept-encoding: gzip, deflate, sdch, br
accept-language: fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4
referer: http://localhost:8080/
cookie: csrftoken=Y7WA181u22l9sScw9UbPxM38wCGQzjaLMMysAesJSWZm89Pj6CCdBkEF01ibpUjW
alexatoolbar-alx_ns_ph: AlexaToolbar/alx-4.0.1
connection: keep-alive

edit removed the : Info.Println line but i still have the same error

thanks

Upvotes: 0

Views: 1698

Answers (3)

Zalberth
Zalberth

Reputation: 308

I've encountered the same issue. Then I found the echo framework (namely github.com/labstack/echo package and its middleware) which can perfectly handle the jsonp request. Here is the demo, cook for jsonp

Hope this could help.

Upvotes: 1

putu
putu

Reputation: 6444

There is a problem in your golang code, the following lines:

decoder := json.NewDecoder(r.Body)
Info.Println(r.Body)
err := decoder.Decode(&geoRec)

Both Info.Println and decoder.Decode read from request body which is an io.Reader. After the execution of Info.Println, the reader is at EOF state. From this point, any further Read will result in EOF error, the error you saw in your application. If you remove (comment out) Info.Println, you will be able to decode the data to the struct.

EDIT:
I forgot and didn't paying attention that JSONP is GET request. The JSON data is embedded in the query. Try the following approach to extract JSON data (please adapt to your need).

//snippet inside recordGeo function
//...

callback := ""
geoRec := geoData{}
queries := r.URL.Query()

//See http://api.jquery.com/jQuery.ajax/
//for 'jsonp' data type parameters.
for key, val := range queries {
    if key == "callback" {
        callback = val[0]
    } else if key == "_" {
        //the Timestamp
    } else {
        //JSON data in the key
        dec := json.NewDecoder(bytes.NewBufferString(key))
        err := dec.Decode(&geoRec)
        if err != nil {
            log.Println(err)
        }
        log.Printf("DATA=%#v", geoRec)
    }
}

//...
//do some processing
response := "{YOUR RESPONSE DATA}"
if callback != "" {
    w.Header().Set("Content-Type", "application/javascript")
    response = fmt.Sprintf("%s(%s);", callback, response)
}
w.Write([]byte(response))

If in the client side you set the data as data: pfg (without JSON.stringify), then in the server side, each parameter will be accessible through query parameter:

//
lon := queries.Get("lo")
lat := queries.Get("la")
acc := queries.Get("ac")

OR, if you set the AJAX request data as data: "mydata=" + JSON.stringify(pfg), then you can extract the data as:

mydata := queries.Get("mydata")
dec := json.NewDecoder(bytes.NewBufferString(mydata))
err := dec.Decode(&geoRec)

After processing, you need to send a proper JSONP response to the client, i.e. callback(DATA);.

Upvotes: 1

jeevatkm
jeevatkm

Reputation: 4781

JSONP is to receive data from the server not the other way around.

You can read more about JSONP - Wikipedia, SO Post and JSONP examples.

Actually it's not specific to Go language, you can implement JSONP handling in any server-side programing.


For your purpose, it seems you need JSON Post request from JavaScript/Jquery. And on Go lang handler do-

func recordGeo(w http.ResponseWriter, req *http.Request) {
    decoder := json.NewDecoder(req.Body)
    var geoRec geoData
    if err := decoder.Decode(&geoRec); err != nil {
        fmt.Println(err)
    }
    defer req.Body.Close()
    fmt.Println(geoRec)
}

Upvotes: 1

Related Questions