Skip to content

Commit dfa0804

Browse files
committed
add a raw gorilla websocket example
1 parent 6760486 commit dfa0804

File tree

5 files changed

+205
-0
lines changed

5 files changed

+205
-0
lines changed

_examples/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@
172172
* [BoltDB](sessions/database/boltdb/main.go)
173173
* [Redis](sessions/database/redis/main.go)
174174
* Websocket
175+
* [Gorilla FileWatch (3rd-party)](websocket/gorilla-filewatch/main.go)
175176
* [Basic](websocket/basic)
176177
* [Server](websocket/basic/server.go)
177178
* [Go Client](websocket/basic/go-client/client.go)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
module gorilla-filewatch-example
2+
3+
go 1.14
4+
5+
require (
6+
github.com/gorilla/websocket v1.4.2
7+
github.com/kataras/iris/v12 v12.1.8
8+
)
9+
10+
replace github.com/kataras/iris/v12 => ../../../
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
//
5+
// This example shows a use case with gorilla webscokets package
6+
// sends a file to the browser client for display whenever the file is modified.
7+
//
8+
// $ go run main.go <name of file to watch>
9+
// # Open http://localhost:8080/ .
10+
// # Modify the file to see it update in the browser.
11+
package main
12+
13+
import (
14+
"flag"
15+
"io/ioutil"
16+
"log"
17+
"os"
18+
"strconv"
19+
"time"
20+
21+
"github.com/gorilla/websocket"
22+
"github.com/kataras/iris/v12"
23+
)
24+
25+
const (
26+
// Time allowed to write the file to the client.
27+
writeWait = 10 * time.Second
28+
29+
// Time allowed to read the next pong message from the client.
30+
pongWait = 60 * time.Second
31+
32+
// Send pings to client with this period. Must be less than pongWait.
33+
pingPeriod = (pongWait * 9) / 10
34+
35+
// Poll file for changes with this period.
36+
filePeriod = 10 * time.Second
37+
)
38+
39+
var (
40+
addr = flag.String("addr", ":8080", "http service address")
41+
filename string
42+
upgrader = websocket.Upgrader{
43+
ReadBufferSize: 1024,
44+
WriteBufferSize: 1024,
45+
}
46+
)
47+
48+
func readFileIfModified(lastMod time.Time) ([]byte, time.Time, error) {
49+
fi, err := os.Stat(filename)
50+
if err != nil {
51+
return nil, lastMod, err
52+
}
53+
if !fi.ModTime().After(lastMod) {
54+
return nil, lastMod, nil
55+
}
56+
p, err := ioutil.ReadFile(filename)
57+
if err != nil {
58+
return nil, fi.ModTime(), err
59+
}
60+
return p, fi.ModTime(), nil
61+
}
62+
63+
func reader(ws *websocket.Conn) {
64+
defer ws.Close()
65+
ws.SetReadLimit(512)
66+
ws.SetReadDeadline(time.Now().Add(pongWait))
67+
ws.SetPongHandler(func(string) error { ws.SetReadDeadline(time.Now().Add(pongWait)); return nil })
68+
for {
69+
_, _, err := ws.ReadMessage()
70+
if err != nil {
71+
break
72+
}
73+
}
74+
}
75+
76+
func writer(ws *websocket.Conn, lastMod time.Time) {
77+
lastError := ""
78+
pingTicker := time.NewTicker(pingPeriod)
79+
fileTicker := time.NewTicker(filePeriod)
80+
defer func() {
81+
pingTicker.Stop()
82+
fileTicker.Stop()
83+
ws.Close()
84+
}()
85+
for {
86+
select {
87+
case <-fileTicker.C:
88+
var p []byte
89+
var err error
90+
91+
p, lastMod, err = readFileIfModified(lastMod)
92+
93+
if err != nil {
94+
if s := err.Error(); s != lastError {
95+
lastError = s
96+
p = []byte(lastError)
97+
}
98+
} else {
99+
lastError = ""
100+
}
101+
102+
if p != nil {
103+
ws.SetWriteDeadline(time.Now().Add(writeWait))
104+
if err := ws.WriteMessage(websocket.TextMessage, p); err != nil {
105+
return
106+
}
107+
}
108+
case <-pingTicker.C:
109+
ws.SetWriteDeadline(time.Now().Add(writeWait))
110+
if err := ws.WriteMessage(websocket.PingMessage, []byte{}); err != nil {
111+
return
112+
}
113+
}
114+
}
115+
}
116+
117+
func serveWs(ctx iris.Context) {
118+
ws, err := upgrader.Upgrade(ctx.ResponseWriter(), ctx.Request(), nil)
119+
if err != nil {
120+
if _, ok := err.(websocket.HandshakeError); !ok {
121+
log.Println(err)
122+
}
123+
return
124+
}
125+
126+
var lastMod time.Time
127+
if n, err := strconv.ParseInt(ctx.FormValue("lastMod"), 16, 64); err == nil {
128+
lastMod = time.Unix(0, n)
129+
}
130+
131+
go writer(ws, lastMod)
132+
reader(ws)
133+
}
134+
135+
func serveHome(ctx iris.Context) {
136+
p, lastMod, err := readFileIfModified(time.Time{})
137+
if err != nil {
138+
p = []byte(err.Error())
139+
lastMod = time.Unix(0, 0)
140+
}
141+
var v = struct {
142+
Host string
143+
Data string
144+
LastMod string
145+
}{
146+
ctx.Host(),
147+
string(p),
148+
strconv.FormatInt(lastMod.UnixNano(), 16),
149+
}
150+
ctx.View("home.html", v)
151+
}
152+
153+
// $ go get github.com/gorilla/websocket
154+
// $ go run main.go testfile.txt
155+
func main() {
156+
flag.Parse()
157+
if flag.NArg() != 1 {
158+
log.Fatal("filename not specified")
159+
}
160+
filename = flag.Args()[0]
161+
162+
app := iris.New()
163+
app.RegisterView(iris.HTML("./views", ".html"))
164+
app.Get("/", serveHome)
165+
app.Any("/ws", serveWs)
166+
167+
app.Listen(*addr)
168+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Some Contents
2+
# you can edit this file locally
3+
# and http://localhost:8080
4+
# will render the new contents through the live websocket connection.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<title>WebSocket Example</title>
5+
</head>
6+
<body>
7+
<pre id="fileData">{{.Data}}</pre>
8+
<script type="text/javascript">
9+
(function() {
10+
var data = document.getElementById("fileData");
11+
var conn = new WebSocket("ws://{{.Host}}/ws?lastMod={{.LastMod}}");
12+
conn.onclose = function(evt) {
13+
data.textContent = 'Connection closed';
14+
}
15+
conn.onmessage = function(evt) {
16+
console.log('file updated');
17+
data.textContent = evt.data;
18+
}
19+
})();
20+
</script>
21+
</body>
22+
</html>

0 commit comments

Comments
 (0)