Skip to content

Instantly share code, notes, and snippets.

@DavidBernal
Forked from sgade/streaming.go
Created November 30, 2017 22:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DavidBernal/5cffa22981d0538916876cd004095ab1 to your computer and use it in GitHub Desktop.
Save DavidBernal/5cffa22981d0538916876cd004095ab1 to your computer and use it in GitHub Desktop.
Golang Streaming Server
package main
import (
"fmt"
"net/http"
"sync"
"time"
)
func main() {
// create a global counter and a mutex for it
mutex := sync.Mutex{}
i := 1
http.HandleFunc("/", func(rw http.ResponseWriter, req *http.Request) {
mutex.Lock()
index := i
i++
mutex.Unlock()
// the function sending text during execution
var waitingText func(string)
// the function sending text that is not time critical
var contentText func(string)
if hj, ok := rw.(http.Hijacker); ok {
// hijack the connection
if con, bufrw, err := hj.Hijack(); err != nil {
http.Error(rw, fmt.Sprintf("Could not hijack connection: %v.", err.Error()), http.StatusInternalServerError)
return
} else {
// we are now responsible for the connection and its data flow
// so make sure to close the connection in the end
defer con.Close()
// and also flush all pending data to the client
defer bufrw.Flush()
contentText = func(input string) {
// simply send the text
if length, err := bufrw.WriteString(input); err != nil {
panic(err)
} else {
fmt.Printf("Sent %q (%v bytes).\n", input, length)
}
}
waitingText = func(input string) {
// send the text
contentText(input)
// make sure it is immediately flushed to the client
if err := bufrw.Flush(); err != nil {
panic(err)
}
fmt.Printf("Sent waiting text.\n")
}
}
} else {
fmt.Printf("Streaming not supported.\n")
waitingText = func(input string) {
// nothing
rw.WriteHeader(http.StatusOK)
}
contentText = func(input string) {
rw.Write([]byte(input))
}
}
// user-interaction
fmt.Printf("Request %v received.\n", index)
waitingText(fmt.Sprintf("Welcome Nr.%v. Plase wait...\n", index))
select {
case <-time.After(3 * time.Second):
contentText("\n")
contentText("Hello World\n")
fmt.Printf("Request %v responded to.\n", index)
}
})
// start the server
done := make(chan bool)
go func() {
err := http.ListenAndServe(":3000", nil)
fmt.Printf("Server crashed: %v.", err)
done <- true
}()
fmt.Printf("Server started!\n")
<-done
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment