diff --git a/README.md b/README.md
index 094889d..a992ecf 100644
--- a/README.md
+++ b/README.md
@@ -1,17 +1,15 @@
-# melody
+# melody [](https://travis-ci.org/olahol/melody) [](https://godoc.org/github.com/olahol/melody)
-[](https://godoc.org/github.com/olahol/melody)
-[](https://travis-ci.org/olahol/melody)
-
-> :notes: Simple websocket framework for Go
+> :notes: Minimalist websocket framework for Go.
Melody is websocket framework based on [github.com/gorilla/websocket](https://github.com/gorilla/websocket)
-that abstracts away the more tedious parts of handling websockets. Features include:
+that abstracts away the tedious parts of handling websockets. It gets out of
+your way so you can write real-time apps. Features include:
-* [x] Timeouts for write and read.
-* [x] Built-in ping/pong handling.
-* [x] Message buffer for connections making concurrent writing easy.
-* [x] Simple broadcasting to all or selected sessions.
+* [x] Clear and easy interface similar to `net/http` or Gin.
+* [x] A simple way to broadcast to all or selected connected sessions.
+* [x] Message buffers making concurrent writing safe.
+* [x] Automatic handling of ping/pong and session timeouts.
## Install
@@ -21,10 +19,10 @@ go get github.com/olahol/melody
## [Example](https://github.com/olahol/melody/tree/master/examples)
-[Simple broadcasting chat server](https://github.com/olahol/melody/tree/master/examples/chat),
+[Multi channel chat server](https://github.com/olahol/melody/tree/master/examples/multichat),
error handling left as en exercise for the developer.
-[](https://github.com/olahol/melody/tree/master/examples/chat)
+[](https://github.com/olahol/melody/tree/master/examples/multichat)
```go
package main
@@ -43,16 +41,24 @@ func main() {
http.ServeFile(c.Writer, c.Request, "index.html")
})
- r.GET("/ws", func(c *gin.Context) {
+ r.GET("/channel/:name", func(c *gin.Context) {
+ http.ServeFile(c.Writer, c.Request, "chan.html")
+ })
+
+ r.GET("/channel/:name/ws", func(c *gin.Context) {
m.HandleRequest(c.Writer, c.Request)
})
m.HandleMessage(func(s *melody.Session, msg []byte) {
- m.Broadcast(msg)
+ m.BroadcastFilter(msg, func(q *melody.Session) bool {
+ return q.Request.URL.Path == s.Request.URL.Path
+ })
})
r.Run(":5000")
}
```
-### [Documentation](https://godoc.org/github.com/olahol/melody)
+### [More examples](https://github.com/olahol/melody/tree/master/examples)
+
+## [Documentation](https://godoc.org/github.com/olahol/melody)
diff --git a/examples/multichat/chan.html b/examples/multichat/chan.html
new file mode 100644
index 0000000..4ea76ba
--- /dev/null
+++ b/examples/multichat/chan.html
@@ -0,0 +1,53 @@
+
+
+ Melody example: chatting
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/multichat/demo.gif b/examples/multichat/demo.gif
new file mode 100644
index 0000000..0bd7afe
Binary files /dev/null and b/examples/multichat/demo.gif differ
diff --git a/examples/multichat/index.html b/examples/multichat/index.html
new file mode 100644
index 0000000..c93fd66
--- /dev/null
+++ b/examples/multichat/index.html
@@ -0,0 +1,34 @@
+
+
+ Melody example: chatting
+
+
+
+
+
+
+ Join a channel
+
+
+
+
+
+
diff --git a/examples/multichat/main.go b/examples/multichat/main.go
new file mode 100644
index 0000000..20c4acd
--- /dev/null
+++ b/examples/multichat/main.go
@@ -0,0 +1,32 @@
+package main
+
+import (
+ "../../"
+ "github.com/gin-gonic/gin"
+ "net/http"
+)
+
+func main() {
+ r := gin.Default()
+ m := melody.New()
+
+ r.GET("/", func(c *gin.Context) {
+ http.ServeFile(c.Writer, c.Request, "index.html")
+ })
+
+ r.GET("/channel/:name", func(c *gin.Context) {
+ http.ServeFile(c.Writer, c.Request, "chan.html")
+ })
+
+ r.GET("/channel/:name/ws", func(c *gin.Context) {
+ m.HandleRequest(c.Writer, c.Request)
+ })
+
+ m.HandleMessage(func(s *melody.Session, msg []byte) {
+ m.BroadcastFilter(msg, func(q *melody.Session) bool {
+ return q.Request.URL.Path == s.Request.URL.Path
+ })
+ })
+
+ r.Run(":5000")
+}
diff --git a/melody.go b/melody.go
index 0b4b982..21a1da7 100644
--- a/melody.go
+++ b/melody.go
@@ -63,14 +63,14 @@ func (m *Melody) HandleError(fn func(*Session, error)) {
}
// Handles a http request and upgrades it to a websocket.
-func (m *Melody) HandleRequest(w http.ResponseWriter, r *http.Request) error {
+func (m *Melody) HandleRequest(w http.ResponseWriter, r *http.Request) {
conn, err := m.upgrader.Upgrade(w, r, nil)
if err != nil {
- return err
+ return
}
- session := newSession(m.Config, conn)
+ session := newSession(m.Config, conn, r)
m.hub.register <- session
@@ -83,8 +83,6 @@ func (m *Melody) HandleRequest(w http.ResponseWriter, r *http.Request) error {
m.hub.unregister <- session
go m.disconnectHandler(session)
-
- return nil
}
// Broadcasts a message to all sessions.
@@ -94,7 +92,7 @@ func (m *Melody) Broadcast(msg []byte) {
}
// Broadcasts a message to all sessions that fn returns true for.
-func (m *Melody) BroadcastFilter(fn func(*Session) bool, msg []byte) {
+func (m *Melody) BroadcastFilter(msg []byte, fn func(*Session) bool) {
message := &envelope{t: websocket.TextMessage, msg: msg, filter: fn}
m.hub.broadcast <- message
}
diff --git a/session.go b/session.go
index 7090ac8..3f4e471 100644
--- a/session.go
+++ b/session.go
@@ -2,21 +2,24 @@ package melody
import (
"github.com/gorilla/websocket"
+ "net/http"
"time"
)
// A melody session.
type Session struct {
- conn *websocket.Conn
- output chan *envelope
- config *Config
+ Request *http.Request
+ conn *websocket.Conn
+ output chan *envelope
+ config *Config
}
-func newSession(config *Config, conn *websocket.Conn) *Session {
+func newSession(config *Config, conn *websocket.Conn, req *http.Request) *Session {
return &Session{
- conn: conn,
- output: make(chan *envelope, config.MessageBufferSize),
- config: config,
+ Request: req,
+ conn: conn,
+ output: make(chan *envelope, config.MessageBufferSize),
+ config: config,
}
}