ms.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. package main
  2. import (
  3. "io"
  4. "math/rand"
  5. "net/http"
  6. "os"
  7. "strconv"
  8. "time"
  9. "github.com/gin-gonic/gin"
  10. "github.com/gorilla/websocket"
  11. )
  12. func main() {
  13. port := "8080"
  14. if os.Getenv("PORT") != "" {
  15. port = os.Getenv("PORT")
  16. }
  17. serverName := "localhost"
  18. if os.Getenv("SERVER_NAME") != "" {
  19. serverName = os.Getenv("SERVER_NAME")
  20. }
  21. rand.Seed(time.Now().Unix())
  22. router := gin.Default()
  23. router.LoadHTMLFiles("index.html")
  24. router.GET("/", func(c *gin.Context) {
  25. c.HTML(http.StatusOK, "index.html", gin.H{
  26. "websocket": "ws://" + serverName + ":" + port + "/ws",
  27. "sse": "http://" + serverName + ":" + port + "/sse",
  28. })
  29. })
  30. router.GET("/ws", websocketHandler(websocket.Upgrader{
  31. Subprotocols: []string{"protocolOne"},
  32. }))
  33. router.GET("/sse", serverSentEventHandler())
  34. router.Run(":" + port)
  35. }
  36. func websocketHandler(upgrader websocket.Upgrader) func(c *gin.Context) {
  37. return func(c *gin.Context) {
  38. conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
  39. if err != nil {
  40. c.AbortWithError(http.StatusInternalServerError, err)
  41. return
  42. }
  43. t := task{}
  44. t.start()
  45. for {
  46. progress, ok := <-t.progress
  47. if !ok {
  48. break
  49. }
  50. if err := conn.WriteMessage(1, []byte(strconv.Itoa(progress))); err != nil {
  51. c.AbortWithError(http.StatusInternalServerError, err)
  52. return
  53. }
  54. }
  55. }
  56. }
  57. func serverSentEventHandler() func(c *gin.Context) {
  58. return func(c *gin.Context) {
  59. t := task{}
  60. t.start()
  61. c.Stream(func(w io.Writer) bool {
  62. progress, ok := <-t.progress
  63. if !ok {
  64. return false
  65. }
  66. c.SSEvent("", strconv.Itoa(progress))
  67. return true
  68. })
  69. }
  70. }
  71. type task struct {
  72. progress chan int
  73. }
  74. func (t *task) start() {
  75. t.progress = make(chan int)
  76. go func() {
  77. p := 0
  78. t.progress <- p
  79. for p < 100 {
  80. if rand.Intn(100) > 50 {
  81. p++
  82. t.progress <- p
  83. }
  84. time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond)
  85. }
  86. close(t.progress)
  87. }()
  88. }