英文:
How to receive a jsonp request in golang
问题
我使用jQuery以jsonp格式发送了一些数据:
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);
}
});
这是我用Golang接收它的代码:
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]
var geoRec geoData
decoder := json.NewDecoder(r.Body)
err := decoder.Decode(&geoRec)
fmt.Println("geoRec")
fmt.Println(geoRec)
checkErr(err)
}
但是我遇到了EOF错误:
2017/07/01 07:16:22 http: panic serving 127.0.0.1:50680: EOF
所以我的问题是如何正确地在Golang中接收一个jsonp请求并将其解析为一个结构体?
这是我在Golang服务器端收到的请求:
GET /geo/rec_geo/?callback=jQuery31108538596418163691_1498913991164&{"lo":1,"la":2,"ac":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
编辑:删除了Info.Println行,但仍然遇到相同的错误。谢谢。
英文:
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
答案1
得分: 1
JSONP
是用于从服务器接收数据,而不是相反的方式。
你可以阅读更多关于 JSONP 的信息 - 维基百科,Stack Overflow 帖子 和 JSONP 示例。
实际上,它不仅适用于 Go 语言,你可以在任何服务器端编程中实现 JSONP 处理。
根据你的目的,似乎你需要从 JavaScript/Jquery 发送 JSON Post 请求。然后在 Go 语言的处理程序中执行以下操作:
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)
}
英文:
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)
}
答案2
得分: 1
你的golang
代码中存在问题,问题出在以下几行代码:
decoder := json.NewDecoder(r.Body)
Info.Println(r.Body)
err := decoder.Decode(&geoRec)
Info.Println
和decoder.Decode
都从请求体中读取数据,而请求体是一个io.Reader
。在执行完Info.Println
之后,读取器处于EOF
状态。从这一点开始,任何进一步的Read
操作都会导致EOF
错误,这也是你在应用程序中看到的错误。如果你移除(注释掉)Info.Println
,你就能够成功将数据解码到结构体中。
编辑:
我忘记并且没有注意到JSONP是一个GET
请求。JSON数据被嵌入在查询中。尝试以下方法来提取JSON数据(请根据你的需求进行调整)。
//在recordGeo函数内部
//...
callback := ""
geoRec := geoData{}
queries := r.URL.Query()
//参考http://api.jquery.com/jQuery.ajax/
//关于'jsonp'数据类型的参数。
for key, val := range queries {
if key == "callback" {
callback = val[0]
} else if key == "_" {
//时间戳
} else {
//在键中的JSON数据
dec := json.NewDecoder(bytes.NewBufferString(key))
err := dec.Decode(&geoRec)
if err != nil {
log.Println(err)
}
log.Printf("DATA=%#v", geoRec)
}
}
//...
//进行一些处理
response := "{YOUR RESPONSE DATA}"
if callback != "" {
w.Header().Set("Content-Type", "application/javascript")
response = fmt.Sprintf("%s(%s);", callback, response)
}
w.Write([]byte(response))
如果在客户端将数据设置为data: pfg
(不使用JSON.stringify
),那么在服务器端,每个参数都可以通过查询参数进行访问:
//
lon := queries.Get("lo")
lat := queries.Get("la")
acc := queries.Get("ac")
或者,如果你将AJAX请求数据设置为data: "mydata=" + JSON.stringify(pfg)
,那么你可以这样提取数据:
mydata := queries.Get("mydata")
dec := json.NewDecoder(bytes.NewBufferString(mydata))
err := dec.Decode(&geoRec)
处理完之后,你需要向客户端发送一个正确的JSONP响应,即callback(DATA);
。
英文:
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);
.
答案3
得分: 1
我遇到了同样的问题。然后我找到了echo框架(即github.com/labstack/echo
包及其中间件),可以完美处理jsonp请求。这里有一个演示,jsonp的示例。
希望这能帮到你。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论