Skip to content

Commit c2cc1ea

Browse files
committed
Merge pull request #4 from meteorhacks/use-net-websocket
Use net websocket
2 parents e5dd457 + 9b5c1cb commit c2cc1ea

File tree

9 files changed

+147
-187
lines changed

9 files changed

+147
-187
lines changed

server/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ func main() {
1818
}
1919

2020
func handler(ctx server.MethodContext) {
21-
n, ok := ctx.Args[0].(float64)
21+
n, ok := ctx.Params[0].(float64)
2222

2323
if !ok {
2424
ctx.SendError("invalid parameters")

server/conn.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package server
2+
3+
import "golang.org/x/net/websocket"
4+
5+
type Conn struct {
6+
ws *websocket.Conn
7+
}
8+
9+
func (c *Conn) ReadJSON(msg interface{}) error {
10+
return websocket.JSON.Receive(c.ws, msg)
11+
}
12+
13+
func (c *Conn) WriteJSON(msg interface{}) error {
14+
return websocket.JSON.Send(c.ws, msg)
15+
}

server/integration/integration_test.go renamed to server/integration_test/integration_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ func TestStartServer(t *testing.T) {
3737
s = server.New()
3838

3939
s.Method("double", func(ctx server.MethodContext) {
40-
n, ok := ctx.Args[0].(float64)
40+
n, ok := ctx.Params[0].(float64)
4141

4242
if !ok {
4343
ctx.SendError("invalid parameters")

server/method_context.go

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,37 @@
11
package server
22

3-
import (
4-
"errors"
5-
)
3+
import "errors"
64

75
type MethodContext struct {
86
ID string
9-
Args []interface{}
10-
Res Response
7+
Params []interface{}
8+
Conn Connection
119
Done bool
1210
Updated bool
1311
}
1412

15-
func NewMethodContext(m Message, res Response) MethodContext {
13+
func NewMethodContext(m Message, conn Connection) MethodContext {
1614
ctx := MethodContext{}
1715
ctx.ID = m.ID
18-
ctx.Args = m.Params
19-
ctx.Res = res
16+
ctx.Params = m.Params
17+
ctx.Conn = conn
2018
return ctx
2119
}
2220

23-
func (ctx *MethodContext) SendResult(r interface{}) error {
21+
func (ctx *MethodContext) SendResult(result interface{}) error {
2422
if ctx.Done {
25-
err := errors.New("already sent results for method")
23+
err := errors.New("results already sent")
2624
return err
2725
}
2826

2927
ctx.Done = true
30-
return ctx.Res.WriteJSON(map[string]interface{}{
28+
msg := map[string]interface{}{
3129
"msg": "result",
3230
"id": ctx.ID,
33-
"result": r,
34-
})
31+
"result": result,
32+
}
33+
34+
return ctx.Conn.WriteJSON(msg)
3535
}
3636

3737
func (ctx *MethodContext) SendError(e string) error {
@@ -41,13 +41,15 @@ func (ctx *MethodContext) SendError(e string) error {
4141
}
4242

4343
ctx.Done = true
44-
return ctx.Res.WriteJSON(map[string]interface{}{
44+
msg := map[string]interface{}{
4545
"msg": "result",
4646
"id": ctx.ID,
4747
"error": map[string]string{
4848
"error": e,
4949
},
50-
})
50+
}
51+
52+
return ctx.Conn.WriteJSON(msg)
5153
}
5254

5355
func (ctx *MethodContext) SendUpdated() error {
@@ -57,8 +59,10 @@ func (ctx *MethodContext) SendUpdated() error {
5759
}
5860

5961
ctx.Updated = true
60-
return ctx.Res.WriteJSON(map[string]interface{}{
62+
msg := map[string]interface{}{
6163
"msg": "updated",
6264
"methods": []string{ctx.ID},
63-
})
65+
}
66+
67+
return ctx.Conn.WriteJSON(msg)
6468
}

server/method_context_test.go

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import (
66
)
77

88
func TestSendResult(t *testing.T) {
9-
r := &TestResponse{}
10-
ctx := MethodContext{ID: "test-id", Res: r}
9+
conn := &TestConn{}
10+
ctx := MethodContext{ID: "test-id", Conn: conn}
1111
err := ctx.SendResult(100)
1212

1313
expected := map[string]interface{}{
@@ -24,28 +24,28 @@ func TestSendResult(t *testing.T) {
2424
t.Error("context must set that a result is sent")
2525
}
2626

27-
if !reflect.DeepEqual(r._data, expected) {
27+
if !reflect.DeepEqual(conn.out, expected) {
2828
t.Error("invalid response for method result")
2929
}
3030
}
3131

3232
func TestSendResultWhenDone(t *testing.T) {
33-
r := &TestResponse{}
34-
ctx := MethodContext{ID: "test-id", Res: r, Done: true}
33+
conn := &TestConn{}
34+
ctx := MethodContext{ID: "test-id", Conn: conn, Done: true}
3535
err := ctx.SendResult(100)
3636

3737
if err == nil {
3838
t.Error("result should be sent only once")
3939
}
4040

41-
if r._data != nil {
41+
if conn.out != nil {
4242
t.Error("result should be sent only once")
4343
}
4444
}
4545

4646
func TestSendError(t *testing.T) {
47-
r := &TestResponse{}
48-
ctx := MethodContext{ID: "test-id", Res: r}
47+
conn := &TestConn{}
48+
ctx := MethodContext{ID: "test-id", Conn: conn}
4949
err := ctx.SendError("test-error")
5050

5151
expected := map[string]interface{}{
@@ -64,28 +64,28 @@ func TestSendError(t *testing.T) {
6464
t.Error("context must set that a result is sent")
6565
}
6666

67-
if !reflect.DeepEqual(r._data, expected) {
67+
if !reflect.DeepEqual(conn.out, expected) {
6868
t.Error("invalid response for method error")
6969
}
7070
}
7171

7272
func TestSendErrorWhenDone(t *testing.T) {
73-
r := &TestResponse{}
74-
ctx := MethodContext{ID: "test-id", Res: r, Done: true}
73+
conn := &TestConn{}
74+
ctx := MethodContext{ID: "test-id", Conn: conn, Done: true}
7575
err := ctx.SendError("test-error")
7676

7777
if err == nil {
7878
t.Error("error should be sent only once")
7979
}
8080

81-
if r._data != nil {
81+
if conn.out != nil {
8282
t.Error("error should be sent only once")
8383
}
8484
}
8585

8686
func TestSendUpdated(t *testing.T) {
87-
r := &TestResponse{}
88-
ctx := MethodContext{ID: "test-id", Res: r}
87+
conn := &TestConn{}
88+
ctx := MethodContext{ID: "test-id", Conn: conn}
8989
err := ctx.SendUpdated()
9090

9191
expected := map[string]interface{}{
@@ -101,21 +101,21 @@ func TestSendUpdated(t *testing.T) {
101101
t.Error("context must set that updated is sent")
102102
}
103103

104-
if !reflect.DeepEqual(r._data, expected) {
104+
if !reflect.DeepEqual(conn.out, expected) {
105105
t.Error("invalid response for method updated")
106106
}
107107
}
108108

109109
func TestSendUpdatedWhenDone(t *testing.T) {
110-
r := &TestResponse{}
111-
ctx := MethodContext{ID: "test-id", Res: r, Updated: true}
110+
conn := &TestConn{}
111+
ctx := MethodContext{ID: "test-id", Conn: conn, Updated: true}
112112
err := ctx.SendUpdated()
113113

114114
if err == nil {
115115
t.Error("updated message should be sent only once")
116116
}
117117

118-
if r._data != nil {
118+
if conn.out != nil {
119119
t.Error("updated message should be sent only once")
120120
}
121121
}

server/server.go

Lines changed: 40 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,118 +1,92 @@
11
package server
22

33
import (
4-
"encoding/json"
5-
"errors"
64
"fmt"
5+
"io"
76
"net/http"
87

9-
"github.com/gorilla/websocket"
108
"github.com/meteorhacks/goddp/utils/random"
9+
"golang.org/x/net/websocket"
1110
)
1211

12+
type Server struct {
13+
methods map[string]MethodHandler
14+
wsserver websocket.Server
15+
}
16+
1317
func New() Server {
1418
s := Server{}
15-
s.methods = make(map[string]MethodFn)
16-
s.upgrader = websocket.Upgrader{
17-
ReadBufferSize: 1024,
18-
WriteBufferSize: 1024,
19-
CheckOrigin: checkOrigin,
20-
}
21-
19+
s.methods = make(map[string]MethodHandler)
20+
s.wsserver = websocket.Server{Handler: s.handler, Handshake: s.handshake}
2221
return s
2322
}
2423

25-
type Server struct {
26-
methods map[string]MethodFn
27-
upgrader websocket.Upgrader
28-
}
29-
3024
func (s *Server) Listen(addr string) error {
31-
http.HandleFunc("/websocket", s.Handler)
32-
http.HandleFunc("/sockjs/websocket", s.Handler)
25+
http.Handle("/websocket", s.wsserver)
26+
http.Handle("/sockjs/websocket", s.wsserver)
3327
return http.ListenAndServe(addr, nil)
3428
}
3529

36-
func (s *Server) Method(name string, fn MethodFn) {
30+
func (s *Server) Method(name string, fn MethodHandler) {
3731
s.methods[name] = fn
3832
}
3933

40-
func (s *Server) Handler(w http.ResponseWriter, r *http.Request) {
41-
ws, err := s.upgrader.Upgrade(w, r, nil)
42-
if err != nil {
43-
// TODO => handle non-websocket requests
44-
return
45-
}
34+
func (s *Server) handshake(config *websocket.Config, req *http.Request) error {
35+
// accept all connections
36+
return nil
37+
}
38+
39+
func (s *Server) handler(ws *websocket.Conn) {
40+
conn := Conn{ws}
41+
defer ws.Close()
4642

4743
for {
48-
msg, err := readMessage(ws)
44+
var msg Message
45+
if err := conn.ReadJSON(&msg); err != nil {
46+
if err != io.EOF {
47+
fmt.Println("Error (Read Error):", err, msg)
48+
}
4949

50-
if err != nil {
5150
break
5251
}
5352

5453
switch msg.Msg {
5554
case "connect":
56-
handleConnect(s, ws, msg)
55+
s.handleConnect(&conn, msg)
5756
case "ping":
58-
handlePing(s, ws, msg)
57+
s.handlePing(&conn, msg)
5958
case "method":
60-
handleMethod(s, ws, msg)
59+
s.handleMethod(&conn, msg)
6160
default:
61+
fmt.Println("Error (Unknown Message Type):", msg)
6262
// TODO => send "error" ddp message
6363
break
6464
}
6565
}
66-
67-
ws.Close()
68-
}
69-
70-
func checkOrigin(r *http.Request) bool {
71-
return true
7266
}
7367

74-
func readMessage(req Request) (Message, error) {
75-
t, str, err := req.ReadMessage()
76-
msg := Message{}
77-
78-
if err != nil {
79-
return msg, err
80-
}
81-
82-
if t != 1 {
83-
err = errors.New("DDP does not supports binary streams yet")
84-
return msg, err
85-
}
86-
87-
if err := json.Unmarshal(str, &msg); err != nil {
88-
return msg, err
89-
}
90-
91-
return msg, nil
92-
}
93-
94-
func handleConnect(s *Server, res Response, m Message) error {
95-
return res.WriteJSON(map[string]string{
68+
func (s *Server) handleConnect(conn Connection, m Message) {
69+
msg := map[string]string{
9670
"msg": "connected",
9771
"session": random.Id(17),
98-
})
72+
}
73+
74+
conn.WriteJSON(msg)
9975
}
10076

101-
func handleMethod(s *Server, res Response, m Message) error {
77+
func (s *Server) handleMethod(conn Connection, m Message) {
10278
fn, ok := s.methods[m.Method]
10379

10480
if !ok {
105-
err := errors.New(fmt.Sprintf("method %s not found", m.Method))
106-
return err
81+
fmt.Println("Error: (Method '%s' Not Found)", m.Method)
82+
return
10783
}
10884

109-
ctx := NewMethodContext(m, res)
85+
ctx := NewMethodContext(m, conn)
11086
go fn(ctx)
111-
112-
return nil
11387
}
11488

115-
func handlePing(s *Server, res Response, m Message) error {
89+
func (s *Server) handlePing(conn Connection, m Message) {
11690
msg := map[string]string{
11791
"msg": "pong",
11892
}
@@ -121,5 +95,5 @@ func handlePing(s *Server, res Response, m Message) error {
12195
msg["id"] = m.ID
12296
}
12397

124-
return res.WriteJSON(msg)
98+
conn.WriteJSON(msg)
12599
}

0 commit comments

Comments
 (0)