Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write a stream API using gin-gonic server in golang? Tried c.Stream didnt work

I wanted to create one streaming API using gin-gonic server in golang.

func StreamData(c *gin.Context) {
    chanStream := make(chan int, 10)
    go func() {for i := 0; i < 5; i++ {
        chanStream <- i
        time.Sleep(time.Second * 1)
    }}()
    c.Stream(func(w io.Writer) bool {
        c.SSEvent("message", <-chanStream)
        return true
    })
}

router.GET("/stream", controller.StreamData)

But when I am trying to hit the endpoint, it just stucks and no response comes. Has someone used the stream function so that he/she can point the mistake which I might be doing. Thanks!

like image 211
kunalag Avatar asked Jun 29 '17 12:06

kunalag


People also ask

What is gin Default ()?

gin. Default() creates a Gin router with default middleware: logger and recovery middleware. Next, we make a handler using router. GET(path, handle) , where path is the relative path,​ and handle is the handler function that takes *gin. Context as an argument.

Who uses gin gonic?

It features a Martini-like API with much better performance that is up to 40 times faster. Gin Gonic can be primarily classified as “Frameworks (Full Stack)” tools. SpartanGeek, Sezzle, and SEASON are some of the popular companies that use Gin Gonic.

What is gin Handlerfunc?

Gin is a web framework written in Go (Golang). It features a martini-like API with much better performance, up to 40 times faster thanks to httprouter. If you need performance and good productivity, you will love Gin.

What is C * gin context?

Returns the specified key from a POST urlencoded form or multipart form when it exists, otherwise it returns the specified defaultValue string. func SomeHandler(c *gin. Context) { key := c. PostForm("key", "default value")


1 Answers

You should return false if the stream ended. And close the chan.

package main

import (
    "io"
    "time"

    "github.com/gin-gonic/contrib/static"
    "github.com/gin-gonic/gin"
    "github.com/mattn/go-colorable"
)

func main() {
    gin.DefaultWriter = colorable.NewColorableStderr()
    r := gin.Default()
    r.GET("/stream", func(c *gin.Context) {
        chanStream := make(chan int, 10)
        go func() {
            defer close(chanStream)
            for i := 0; i < 5; i++ {
                chanStream <- i
                time.Sleep(time.Second * 1)
            }
        }()
        c.Stream(func(w io.Writer) bool {
            if msg, ok := <-chanStream; ok {
                c.SSEvent("message", msg)
                return true
            }
            return false
        })
    })
    r.Use(static.Serve("/", static.LocalFile("./public", true)))
    r.Run()
}

Additional

Client code should be:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<script>
var stream = new EventSource("/stream");
stream.addEventListener("message", function(e){
    console.log(e.data);
});
</script>    
</body>
</html>
like image 110
mattn Avatar answered Sep 18 '22 20:09

mattn