room_login.templ.html 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="utf-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1">
  7. <title>Server-Sent Events. Room "{{.roomid}}"</title>
  8. <!-- jQuery -->
  9. <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
  10. <script src="http://malsup.github.com/jquery.form.js"></script>
  11. <!-- EPOCH -->
  12. <script src="http://d3js.org/d3.v3.min.js"></script>
  13. <script src="/static/epoch.min.js"></script>
  14. <link rel="stylesheet" href="/static/epoch.min.css">
  15. <script src="/static/realtime.js"></script>
  16. <!-- Latest compiled and minified CSS -->
  17. <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
  18. <!-- Optional theme -->
  19. <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css">
  20. <!-- Latest compiled and minified JavaScript -->
  21. <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
  22. <!-- Primjs -->
  23. <link href="/static/prismjs.min.css" rel="stylesheet" />
  24. <script type="text/javascript">
  25. $(document).ready(function() {
  26. StartRealtime({{.roomid}}, {{.timestamp}});
  27. });
  28. </script>
  29. <style>
  30. body { padding-top: 50px; }
  31. </style>
  32. </head>
  33. <body>
  34. <nav class="navbar navbar-fixed-top navbar-inverse">
  35. <div class="container">
  36. <div class="navbar-header">
  37. <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
  38. <span class="sr-only">Toggle navigation</span>
  39. <span class="icon-bar"></span>
  40. <span class="icon-bar"></span>
  41. <span class="icon-bar"></span>
  42. </button>
  43. <a class="navbar-brand" href="#">Server-Sent Events</a>
  44. </div>
  45. <div id="navbar" class="collapse navbar-collapse">
  46. <ul class="nav navbar-nav">
  47. <li class="active"><a href="#">Demo</a></li>
  48. <li><a href="http://www.w3.org/TR/2009/WD-eventsource-20091029/">W3 Standard</a></li>
  49. <li><a href="http://caniuse.com/#feat=eventsource">Browser Support</a></li>
  50. <li><a href="http://gin-gonic.github.io/gin/">Gin Framework</a></li>
  51. <li><a href="https://github.com/gin-gonic/gin/tree/develop/examples/realtime-advanced">Github</a></li>
  52. </ul>
  53. </div><!-- /.nav-collapse -->
  54. </div><!-- /.container -->
  55. </nav><!-- /.navbar -->
  56. <!-- Main jumbotron for a primary marketing message or call to action -->
  57. <div class="jumbotron">
  58. <div class="container">
  59. <h1>Server-Sent Events in Go</h1>
  60. <p>Server-sent events (SSE) is a technology where a browser receives automatic updates from a server via HTTP connection. It is not websockets. <a href="http://www.html5rocks.com/en/tutorials/eventsource/basics/">Learn more.</a></p>
  61. <p>The chat and the charts data is provided in realtime using the SSE implemention of <a href="https://github.com/gin-gonic/gin/blob/15b0c49da556d58a3d934b86e3aa552ff224026d/examples/realtime-chat/main.go#L23-L32">Gin Framework</a>.</p>
  62. <div class="row">
  63. <div class="col-md-8">
  64. <div id="chat-scroll" style="overflow-y:scroll; overflow-x:scroll; height:290px">
  65. <table id="table-style" class="table" data-show-header="false">
  66. <thead>
  67. <tr>
  68. <th data-field="nick" class="col-md-2">Nick</th>
  69. <th data-field="message" class="col-md-8">Message</th>
  70. </tr>
  71. </thead>
  72. <tbody id="chat"></tbody>
  73. </table>
  74. </div>
  75. {{if .nick}}
  76. <form autocomplete="off" class="form-inline" id="chat-form" action="/room-post/{{.roomid}}?nick={{.nick}}" method="post">
  77. <div class="form-group">
  78. <label class="sr-only" for="chat-message">Message</label>
  79. <div class="input-group">
  80. <div class="input-group-addon">{{.nick}}</div>
  81. <input type="text" name="message" id="chat-message" class="form-control" placeholder="a message" value="" />
  82. </div>
  83. </div>
  84. <input type="submit" class="btn btn-primary" value="Send" />
  85. </form>
  86. {{else}}
  87. <form action="" method="get" class="form-inline">
  88. <legend>Join the SSE real-time chat</legend>
  89. <div class="form-group">
  90. <input value='' name="nick" id="nick" placeholder="Your Name" type="text" class="form-control" />
  91. </div>
  92. <div class="form-group text-center">
  93. <input type="submit" class="btn btn-success btn-login-submit" value="Join" />
  94. </div>
  95. </form>
  96. {{end}}
  97. </div>
  98. <div class="col-md-4">
  99. <div id="messagesChart" class="epoch category10"></div>
  100. <p>
  101. <span style="font-size:20px; color:#1f77b4">◼︎</span> Users<br>
  102. <span style="font-size:20px; color:#ff7f0e">◼︎</span> Inbound messages / sec<br>
  103. <span style="font-size:20px; color:#2ca02c">◼︎</span> Outbound messages / sec<br>
  104. </p>
  105. </div>
  106. </div>
  107. </div>
  108. </div>
  109. <div class="container">
  110. <div class="row">
  111. <h2>Realtime server Go stats</h2>
  112. <div class="col-md-6">
  113. <h3>Memory usage</h3>
  114. <p>
  115. <div id="heapChart" class="epoch category20c"></div>
  116. </p>
  117. <p>
  118. <span style="font-size:20px; color:#1f77b4">◼︎</span> Heap bytes<br>
  119. <span style="font-size:20px; color:#aec7e8">◼︎</span> Stack bytes<br>
  120. </p>
  121. </div>
  122. <div class="col-md-6">
  123. <h3>Allocations per second</h3>
  124. <p>
  125. <div id="mallocsChart" class="epoch category20b"></div>
  126. </p>
  127. <p>
  128. <span style="font-size:20px; color:#393b79">◼︎</span> Mallocs / sec<br>
  129. <span style="font-size:20px; color:#5254a3">◼︎</span> Frees / sec<br>
  130. </p>
  131. </div>
  132. </div>
  133. <div class="row">
  134. <h2>MIT Open Sourced</h2>
  135. <ul>
  136. <li><a href="https://github.com/gin-gonic/gin/tree/develop/examples/realtime-advanced">This demo website (JS and Go)</a></li>
  137. <li><a href="https://github.com/manucorporat/sse">The SSE implementation in Go</a></li>
  138. <li><a href="https://github.com/gin-gonic/gin">The Web Framework (Gin)</a></li>
  139. </ul>
  140. <div class="col-md-6">
  141. <script src="/static/prismjs.min.js"></script>
  142. <h3>Server-side (Go)</h3>
  143. <pre><code class="language-go">func streamRoom(c *gin.Context) {
  144. roomid := c.ParamValue(&quot;roomid&quot;)
  145. listener := openListener(roomid)
  146. statsTicker := time.NewTicker(1 * time.Second)
  147. defer closeListener(roomid, listener)
  148. defer statsTicker.Stop()
  149. c.Stream(func(w io.Writer) bool {
  150. select {
  151. case msg := &lt;-listener:
  152. c.SSEvent(&quot;message&quot;, msg)
  153. case &lt;-statsTicker.C:
  154. c.SSEvent(&quot;stats&quot;, Stats())
  155. }
  156. return true
  157. })
  158. }</code></pre>
  159. </div>
  160. <div class="col-md-6">
  161. <h3>Client-side (JS)</h3>
  162. <pre><code class="language-javascript">function StartSSE(roomid) {
  163. var source = new EventSource('/stream/'+roomid);
  164. source.addEventListener('message', newChatMessage, false);
  165. source.addEventListener('stats', stats, false);
  166. }</code></pre>
  167. </div>
  168. </div>
  169. <div class="row">
  170. <div class="col-md-12">
  171. <h3>SSE package</h3>
  172. <pre><code class="language-go">import &quot;github.com/manucorporat/sse&quot;
  173. func httpHandler(w http.ResponseWriter, req *http.Request) {
  174. // data can be a primitive like a string, an integer or a float
  175. sse.Encode(w, sse.Event{
  176. Event: &quot;message&quot;,
  177. Data: &quot;some data\nmore data&quot;,
  178. })
  179. // also a complex type, like a map, a struct or a slice
  180. sse.Encode(w, sse.Event{
  181. Id: &quot;124&quot;,
  182. Event: &quot;message&quot;,
  183. Data: map[string]interface{}{
  184. &quot;user&quot;: &quot;manu&quot;,
  185. &quot;date&quot;: time.Now().Unix(),
  186. &quot;content&quot;: &quot;hi!&quot;,
  187. },
  188. })
  189. }</code></pre>
  190. <pre>event: message
  191. data: some data\\nmore data
  192. id: 124
  193. event: message
  194. data: {&quot;content&quot;:&quot;hi!&quot;,&quot;date&quot;:1431540810,&quot;user&quot;:&quot;manu&quot;}</pre>
  195. </div>
  196. </div>
  197. <hr>
  198. <footer>
  199. <p>Created with <span class="glyphicon glyphicon-heart"></span> by <a href="https://github.com/manucorporat">Manu Martinez-Almeida</a></p>
  200. </footer>
  201. </div>
  202. </body>
  203. </html>