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

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);.

javascript - How to receive a jsonp request in golang, 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  Modifythe path in server.goto the path where you place demo.jsand index.html. Run the server by: $ go run server.go. Open your browser with URL localhost:8000. Open theconsole of the browser, and you will see the data printed out by the callbackfunction.

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)
}

go-chi/jsonp: JSONP Go http middleware, The code is small, so go read it, but it just buffers the response from the rest of the chain, and if its a JSON request with a callback, then it will wrap the response  The basic idea of JSONP server is as follows: Get the name of front-end callback function from the query string in HTTP request. Encode the data to be returned to the client in JSON format. In this case, it's the HTTP headers encoded in JSON. Set the Content-Type as application/javascript in HTTP response.

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.

How to Parse a JSON Request Body in Go, A client can include extra unexpected fields in their JSON, and these fields will be silently ignored without the client receiving any error. We can fix  Web developers make http requests all the time. In this post, we’re going to make some http requests using Golang. I am going to show you how I make http GET and POST requests using the net/http built-in package. Golang Http. Golang http package offers convenient functions like Get, Post, Head for common http requests. Let’s see the

[Golang] JSONP Server Implementation Code, Get the name of front-end callback function from the query string in HTTP request. Encode the data to be returned to the client in JSON format. In  r/golang: Ask questions and post articles about the Go programming language and related tools, events etc. Press J to jump to the feed. Press question mark to learn the rest of the keyboard shortcuts

JSONP Recipe, JSONP recipe for Echo | Echo is a high performance, extensible, minimalist web GET("/jsonp", func(c echo.Context) error { callback := c.QueryParam("callback") var content struct { Response string `json:"response"` Timestamp time. Requesting a file from another domain can cause problems, due to cross-domain policy. Requesting an external script from another domain does not have this problem.. JSONP uses this advantage, and request files using the script tag instead of the XMLHttpRequest object.

How would I parse JSONP? : golang, I think trimming the string will get you results faster than including a javascript VM readers; it does not require you to manifest in memory any complete request. Introduction. To detect browser language preference (user locale ), one of the solution is to access Accept-Language field in HTTP Request Header. We cannot, however, access the Accept-Language field in our browser code directly. One of the answers in Stack Overflow question [4] provides an cloud service on Google App Engine to return you the HTTP request headers via JSONP.

Comments
  • Even with removing the info.Println i still have the same EOF error ...
  • @user462794 to debug, just after recordGeo function, use ioutil.ReadAll to read the content of the request body, then print it to the console and post it here.
  • @user462794 I've edit the answer, please take a look
  • fmt.Sprintf rather than fmt.Printf near the end
  • @spekary, Thank you. Answer was modified.