如何在 golang 中接收 jsonp 请求
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]
Info.Println("4")
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&{%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
编辑删除了:
Info.Println行
但我仍然有同样的错误
谢谢
JSONP
是从服务器接收数据而不是反过来
您可以阅读更多关于 JSONP - Wikipedia, SO Post and JSONP examples。
其实它不是Go语言特有的,你可以在任何服务器端编程中实现JSONP处理。
为了您的目的,您似乎需要 JSON Post 来自 JavaScript/Jquery 的请求。在 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)
}
你的golang
代码有问题,如下几行:
decoder := json.NewDecoder(r.Body)
Info.Println(r.Body)
err := decoder.Decode(&geoRec)
Info.Println
和 decoder.Decode
都从请求正文中读取 io.Reader
。 Info.Println
执行后,reader处于EOF
状态。从这一点开始,任何进一步的 Read
将导致 EOF
错误,即您在应用程序中看到的错误。如果您删除(注释掉)Info.Println
,您将能够将数据解码为结构。
编辑:
我忘了也没有注意 JSONP 是 GET
请求。 JSON 数据嵌入在查询中。尝试以下方法提取 JSON 数据(请根据您的需要进行调整)。
//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))
如果在客户端将数据设置为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);
.
我遇到了同样的问题。然后我找到了可以完美处理jsonp请求的echo框架(即github.com/labstack/echo
包及其中间件)。这是演示,cook for jsonp
希望这对您有所帮助。
我使用 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]
Info.Println("4")
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&{%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
编辑删除了: Info.Println行 但我仍然有同样的错误
谢谢
JSONP
是从服务器接收数据而不是反过来
您可以阅读更多关于 JSONP - Wikipedia, SO Post and JSONP examples。
其实它不是Go语言特有的,你可以在任何服务器端编程中实现JSONP处理。
为了您的目的,您似乎需要 JSON Post 来自 JavaScript/Jquery 的请求。在 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)
}
你的golang
代码有问题,如下几行:
decoder := json.NewDecoder(r.Body)
Info.Println(r.Body)
err := decoder.Decode(&geoRec)
Info.Println
和 decoder.Decode
都从请求正文中读取 io.Reader
。 Info.Println
执行后,reader处于EOF
状态。从这一点开始,任何进一步的 Read
将导致 EOF
错误,即您在应用程序中看到的错误。如果您删除(注释掉)Info.Println
,您将能够将数据解码为结构。
编辑:
我忘了也没有注意 JSONP 是 GET
请求。 JSON 数据嵌入在查询中。尝试以下方法提取 JSON 数据(请根据您的需要进行调整)。
//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))
如果在客户端将数据设置为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);
.
我遇到了同样的问题。然后我找到了可以完美处理jsonp请求的echo框架(即github.com/labstack/echo
包及其中间件)。这是演示,cook for jsonp
希望这对您有所帮助。