从 API 流式传输数据

我正在尝试从电子邮件测试工具 mailhog 中提取有关进入 API 的邮件数据。如果我使用调用来获取电子邮件列表,例如 GET /api/v1/messages,我可以毫无问题地将这些数据加载到一个结构中,并打印出我需要的值。


但是,如果我使用一个不同的端点,它本质上是一个新的电子邮件流,我会有不同的行为。当我运行我的 go 应用程序时,我没有得到任何输出。


我是否需要像 while 循环一样不断地监听端点以获取输出?我的最终目标是在电子邮件进入时从中提取一些信息,然后将它们传递给不同的功能。


这是我尝试访问流式传输端点 https://github.com/mailhog/MailHog/blob/master/docs/APIv1.md


res, err := http.Get("http://localhost:8084/api/v1/events")


if err != nil {

    panic(err.Error())

}

body, err := ioutil.ReadAll(res.Body)


if err != nil {

    panic(err.Error())

}


var data Email

json.Unmarshal(body, &data)

fmt.Printf("Email: %v\n", data)

如果我在具有相同端点的 mailhog 服务上执行 curl 请求,我会在收到邮件时得到输出。但是我似乎无法弄清楚为什么我的 go 应用程序没有得到任何输出。该应用程序确实保持运行,只是我没有得到任何输出。


如果这是一个非常简单的问题,我是 Go 的新手,所以很抱歉


MMMHUHU
浏览 79回答 1
1回答

缥缈止盈

从ioutil.ReadAll文档:ReadAll 从 r 读取直到出现错误或 EOF 并返回它读取的数据。当您用来读取常规端点的正文时,它会起作用,因为有效负载有一个EOF:服务器使用标头来Content-Length告诉正文响应有多少字节,一旦客户端读取了那么多字节,它就会明白它已经读取了全身上下都可以停下来。但是,您的“流”端点没有使用,因为正文的大小未知,它应该在事件到来时写入事件,因此在这种情况下Content-Length您不能使用。ReadAll通常,在这种情况下,您应该逐行阅读,其中每行代表一个事件。bufio.Scanner正是这样做的:res, err := http.Get("http://localhost:8084/api/v1/events")if err != nil {    panic(err.Error())}scanner := bufio.NewScanner(res.Body)for e.scanner.Scan() {    if err := e.scanner.Err(); err != nil {        panic(err.Error())    }    event := e.scanner.Bytes()    var data Email    json.Unmarshal(event, &data)    fmt.Printf("Email: %v\n", data)}curl可以按预期处理响应,因为它会检查端点是否会流式传输数据,因此它会相应地做出反应。添加对问题的响应可能会有所帮助curl。
打开App,查看更多内容
随时随地看视频慕课网APP