Init · go-siris/siris-examples@be36beb · GitHub
Skip to content
This repository was archived by the owner on Aug 3, 2026. It is now read-only.

Commit be36beb

Browse files
Erwin RenkemaErwin Renkema
authored andcommitted
Init
1 parent 93af71d commit be36beb

167 files changed

Lines changed: 33076 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎README.md‎

Lines changed: 110 additions & 0 deletions

‎advanced/online-visitors/main.go‎

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
package main
2+
3+
import (
4+
"sync/atomic"
5+
6+
"github.com/go-siris/siris"
7+
"github.com/go-siris/siris/context"
8+
9+
"github.com/go-siris/siris/view"
10+
"github.com/go-siris/siris/websocket"
11+
)
12+
13+
var (
14+
app *siris.Application
15+
ws websocket.Server
16+
)
17+
18+
func init() {
19+
// init the server instance
20+
app = siris.New()
21+
// load templaes
22+
app.AttachView(view.HTML("./templates", ".html").Reload(true))
23+
// attach websocket server
24+
ws = websocket.New(websocket.Config{Endpoint: "/my_endpoint"})
25+
ws.OnConnection(HandleWebsocketConnection)
26+
ws.Attach(app)
27+
}
28+
29+
type page struct {
30+
PageID string
31+
}
32+
33+
func main() {
34+
app.StaticWeb("/js", "./static/assets/js")
35+
36+
h := func(ctx context.Context) {
37+
ctx.ViewData("", page{PageID: "index page"})
38+
ctx.View("index.html")
39+
}
40+
41+
h2 := func(ctx context.Context) {
42+
ctx.ViewData("", page{PageID: "other page"})
43+
ctx.View("other.html")
44+
}
45+
46+
// Open some browser tabs/or windows
47+
// and navigate to
48+
// http://localhost:8080/ and http://localhost:8080/other multiple times.
49+
// Each page has its own online-visitors counter.
50+
app.Get("/", h)
51+
app.Get("/other", h2)
52+
app.Run(siris.Addr(":8080"))
53+
}
54+
55+
type pageView struct {
56+
source string
57+
count uint64
58+
}
59+
60+
func (v *pageView) increment() {
61+
atomic.AddUint64(&v.count, 1)
62+
}
63+
64+
func (v *pageView) decrement() {
65+
oldCount := v.count
66+
if oldCount > 0 {
67+
atomic.StoreUint64(&v.count, oldCount-1)
68+
}
69+
}
70+
71+
func (v *pageView) getCount() uint64 {
72+
val := atomic.LoadUint64(&v.count)
73+
return val
74+
}
75+
76+
type (
77+
pageViews []pageView
78+
)
79+
80+
func (v *pageViews) Add(source string) {
81+
args := *v
82+
n := len(args)
83+
for i := 0; i < n; i++ {
84+
kv := &args[i]
85+
if kv.source == source {
86+
kv.increment()
87+
return
88+
}
89+
}
90+
91+
c := cap(args)
92+
if c > n {
93+
args = args[:n+1]
94+
kv := &args[n]
95+
kv.source = source
96+
kv.count = 1
97+
*v = args
98+
return
99+
}
100+
101+
kv := pageView{}
102+
kv.source = source
103+
kv.count = 1
104+
*v = append(args, kv)
105+
}
106+
107+
func (v *pageViews) Get(source string) *pageView {
108+
args := *v
109+
n := len(args)
110+
for i := 0; i < n; i++ {
111+
kv := &args[i]
112+
if kv.source == source {
113+
return kv
114+
}
115+
}
116+
return nil
117+
}
118+
119+
func (v *pageViews) Reset() {
120+
*v = (*v)[:0]
121+
}
122+
123+
var v pageViews
124+
125+
// HandleWebsocketConnection handles the online viewers per example(gist source)
126+
func HandleWebsocketConnection(c websocket.Connection) {
127+
128+
c.On("watch", func(pageSource string) {
129+
v.Add(pageSource)
130+
// join the socket to a room linked with the page source
131+
c.Join(pageSource)
132+
133+
viewsCount := v.Get(pageSource).getCount()
134+
if viewsCount == 0 {
135+
viewsCount++ // count should be always > 0 here
136+
}
137+
c.To(pageSource).Emit("watch", viewsCount)
138+
})
139+
140+
c.OnLeave(func(roomName string) {
141+
if roomName != c.ID() { // if the roomName it's not the connection iself
142+
// the roomName here is the source, this is the only room(except the connection's ID room) which we join the users to.
143+
pageV := v.Get(roomName)
144+
if pageV == nil {
145+
return // for any case that this room is not a pageView source
146+
}
147+
// decrement -1 the specific counter for this page source.
148+
pageV.decrement()
149+
// 1. open 30 tabs.
150+
// 2. close the browser.
151+
// 3. re-open the browser
152+
// 4. should be v.getCount() = 1
153+
// in order to achieve the previous flow we should decrement exactly when the user disconnects
154+
// but emit the result a little after, on a goroutine
155+
// getting all connections within this room and emit the online views one by one.
156+
// note:
157+
// we can also add a time.Sleep(2-3 seconds) inside the goroutine at the future if we don't need 'real-time' updates.
158+
go func(currentConnID string) {
159+
for _, conn := range ws.GetConnectionsByRoom(roomName) {
160+
if conn.ID() != currentConnID {
161+
conn.Emit("watch", pageV.getCount())
162+
}
163+
164+
}
165+
}(c.ID())
166+
}
167+
168+
})
169+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
(function() {
2+
var socket = new Ws("ws://localhost:8080/my_endpoint");
3+
4+
socket.OnConnect(function () {
5+
socket.Emit("watch", PAGE_SOURCE);
6+
});
7+
8+
9+
socket.On("watch", function (onlineViews) {
10+
var text = "1 online view";
11+
if (onlineViews > 1) {
12+
text = onlineViews + " online views";
13+
}
14+
document.getElementById("online_views").innerHTML = text;
15+
});
16+
17+
socket.OnDisconnect(function () {
18+
document.getElementById("online_views").innerHTML = "you've been disconnected";
19+
});
20+
21+
})();
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<html>
2+
3+
<head>
4+
<title>Online visitors example</title>
5+
<style>
6+
body {
7+
margin: 0;
8+
font-family: -apple-system, "San Francisco", "Helvetica Neue", "Noto", "Roboto", "Calibri Light", sans-serif;
9+
color: #212121;
10+
font-size: 1.0em;
11+
line-height: 1.6;
12+
}
13+
14+
.container {
15+
max-width: 750px;
16+
margin: auto;
17+
padding: 15px;
18+
}
19+
20+
#online_views {
21+
font-weight: bold;
22+
font-size: 18px;
23+
}
24+
</style>
25+
</head>
26+
27+
<body>
28+
<div class="container">
29+
<span id="online_views">1 online view</span>
30+
</div>
31+
32+
<script type="text/javascript">
33+
/* take the page source from our passed struct on .Render */
34+
var PAGE_SOURCE = {{ .PageID }}
35+
</script>
36+
37+
<script src="/siris-ws.js"></script>
38+
39+
<script src="/js/visitors.js"></script>
40+
41+
</body>
42+
43+
</html>
Lines changed: 29 additions & 0 deletions

0 commit comments

Comments
 (0)