【问题标题】:How to receive a jsonp request in golanggolang如何接收jsonp请求
【发布时间】:2018-11-18 19:56:44
【问题描述】:

我使用 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

edit 删除了 : Info.Println 行 但我仍然有同样的错误

谢谢

【问题讨论】:

    标签: javascript jquery go jsonp


    【解决方案1】:

    您的golang 代码有问题,以下几行:

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

    Info.Printlndecoder.Decode 都从请求正文中读取,这是一个 io.ReaderInfo.Println执行后,阅读器处于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);

    【讨论】:

    • 即使删除 info.Println 我仍然有相同的 EOF 错误 ...
    • @user462794 进行调试,在recordGeo 函数之后,使用ioutil.ReadAll 读取请求体的内容,然后打印到控制台并发布到这里。
    • @user462794 我已经编辑了答案,请看一下
    • fmt.Sprintf 而不是 fmt.Printf 接近尾声
    • @spekary,谢谢。答案已修改。
    【解决方案2】:

    JSONP 是从服务器接收数据,而不是相反。

    您可以阅读有关 JSONP 的更多信息 - WikipediaSO PostJSONP examples

    其实它并不是 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)
    }
    

    【讨论】:

      【解决方案3】:

      我也遇到过同样的问题。然后我找到了可以完美处理jsonp请求的echo框架(即github.com/labstack/echo包及其中间件)。这是演示,cook for jsonp

      希望这会有所帮助。

      【讨论】:

        猜你喜欢
        • 2012-05-10
        • 2017-06-20
        • 2013-11-23
        • 1970-01-01
        • 2012-11-08
        • 1970-01-01
        • 2021-12-25
        • 1970-01-01
        • 2013-12-07
        相关资源
        最近更新 更多