Skip to content

Commit 81ceab0

Browse files
committed
Changing both the Handler API and the Socket API, for better consistency
1 parent 4b20152 commit 81ceab0

8 files changed

+54
-33
lines changed

CONTRIBUTING.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ I am very open to discussing the design of the API and what can be made better.
1313

1414
## TODO List
1515

16-
- Change the handlers to have proper context from the request.
16+
- Make the javascript interop better than the Phoenix design.
1717
- Missing events, throttle, debounce etc.
1818
- File uploads
1919
- Tests... Lots of tests

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ func NewGreeter(ID string, h *live.Handler, s *live.Socket, name string) (Compon
104104
ID,
105105
h,
106106
s,
107-
WithMount(func(ctx context.Context, c *Component, r *http.Request, connected bool) error {
107+
WithMount(func(ctx context.Context, c *Component, r *http.Request) error {
108108
c.State = name
109109
return nil
110110
}),

example_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ func Example_temperature() {
5555

5656
// Mount function is called on initial HTTP load and then initial web
5757
// socket connection. This should be used to create the initial state,
58-
// the connected variable will be true if the mount call is on a web
58+
// the socket Connectedi func will be true if the mount call is on a web
5959
// socket connection.
60-
h.Mount = func(ctx context.Context, h *Handler, r *http.Request, s *Socket, connected bool) (interface{}, error) {
60+
h.Mount = func(ctx context.Context, r *http.Request, s *Socket) (interface{}, error) {
6161
return NewThermoModel(s), nil
6262
}
6363

handler.go

+14-14
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import (
2121
// MountHandler the func that is called by a handler to gather data to
2222
// be rendered in a template. This is called on first GET and then later when
2323
// the web socket first connects.
24-
type MountHandler func(ctx context.Context, h *Handler, r *http.Request, c *Socket, connected bool) (interface{}, error)
24+
type MountHandler func(ctx context.Context, r *http.Request, c *Socket) (interface{}, error)
2525

2626
// RenderHandler the func that is called to render the current state of the
2727
// data for the socket.
@@ -77,7 +77,7 @@ func NewHandler(store SessionStore, configs ...HandlerConfig) (*Handler, error)
7777
broadcastLimiter: rate.NewLimiter(rate.Every(time.Millisecond*100), 8),
7878
eventHandlers: make(map[string]EventHandler),
7979
selfHandlers: make(map[string]EventHandler),
80-
Mount: func(ctx context.Context, hd *Handler, r *http.Request, c *Socket, connected bool) (interface{}, error) {
80+
Mount: func(ctx context.Context, r *http.Request, c *Socket) (interface{}, error) {
8181
return nil, nil
8282
},
8383
Render: func(ctx context.Context, data interface{}) (io.Reader, error) {
@@ -122,11 +122,6 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
122122
return
123123
}
124124

125-
// Self sends a message to the socket on this view.
126-
func (h *Handler) Self(ctx context.Context, sock *Socket, msg Event) {
127-
handleEmittedEvent(ctx, h, sock, msg)
128-
}
129-
130125
// Broadcast send a message to all sockets connected to this view.
131126
func (h *Handler) Broadcast(msg Event) {
132127
ctx := context.Background()
@@ -140,7 +135,7 @@ func (h *Handler) HandleEvent(t string, handler EventHandler) {
140135
h.eventHandlers[t] = handler
141136
}
142137

143-
// HandleSelf handles an event that comes from the view. For example calling
138+
// HandleSelf handles an event that comes from the server side socket. For example calling
144139
// h.Self(socket, msg) will be handled here.
145140
func (h *Handler) HandleSelf(t string, handler EventHandler) {
146141
h.selfHandlers[t] = handler
@@ -152,6 +147,11 @@ func (h *Handler) HandleParams(handler EventHandler) {
152147
h.paramsHandlers = append(h.paramsHandlers, handler)
153148
}
154149

150+
// self sends a message to the socket on this view.
151+
func (h *Handler) self(ctx context.Context, sock *Socket, msg Event) {
152+
handleEmittedEvent(ctx, h, sock, msg)
153+
}
154+
155155
// serveHTTP serve an http request to the view.
156156
func (h *Handler) serveHTTP(w http.ResponseWriter, r *http.Request) {
157157
// Get session.
@@ -162,16 +162,16 @@ func (h *Handler) serveHTTP(w http.ResponseWriter, r *http.Request) {
162162
}
163163

164164
// Get socket.
165-
sock := NewSocket(session)
165+
sock := NewSocket(session, h, false)
166166

167167
// Run mount, this generates the data for the page we are on.
168-
if err := sock.mount(r.Context(), h, r, false); err != nil {
168+
if err := sock.mount(r.Context(), h, r); err != nil {
169169
h.Error(r.Context(), w, r, err)
170170
return
171171
}
172172

173173
// Handle any query parameters that are on the page.
174-
if err := sock.params(r.Context(), h, r, false); err != nil {
174+
if err := sock.params(r.Context(), h, r); err != nil {
175175
h.Error(r.Context(), w, r, err)
176176
return
177177
}
@@ -236,7 +236,7 @@ type eventError struct {
236236
func (h *Handler) _serveWS(r *http.Request, session Session, c *websocket.Conn) error {
237237
ctx := r.Context()
238238
// Get the sessions socket and register it with the server.
239-
sock := NewSocket(session)
239+
sock := NewSocket(session, h, true)
240240
sock.assignWS(c)
241241
h.addSocket(sock)
242242
defer h.deleteSocket(sock)
@@ -296,12 +296,12 @@ func (h *Handler) _serveWS(r *http.Request, session Session, c *websocket.Conn)
296296

297297
// Run mount again now that eh socket is connected, passing true indicating
298298
// a connection has been made.
299-
if err := sock.mount(ctx, h, r, true); err != nil {
299+
if err := sock.mount(ctx, h, r); err != nil {
300300
return fmt.Errorf("socket mount error: %w", err)
301301
}
302302

303303
// Run params again now that the socket is connected.
304-
if err := sock.params(r.Context(), h, r, true); err != nil {
304+
if err := sock.params(r.Context(), h, r); err != nil {
305305
return fmt.Errorf("socket params error: %w", err)
306306
}
307307

page/component.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import (
1414
type RegisterHandler func(c *Component) error
1515

1616
// MountHandler the components mount function called on first GET request and again when the socket connects.
17-
type MountHandler func(ctx context.Context, c *Component, r *http.Request, connected bool) error
17+
type MountHandler func(ctx context.Context, c *Component, r *http.Request) error
1818

1919
// RenderHandler ths component.
2020
type RenderHandler func(w io.Writer, c *Component) error
@@ -80,7 +80,7 @@ func Init(ctx context.Context, construct func() (Component, error)) (Component,
8080
if err := comp.Register(&comp); err != nil {
8181
return Component{}, fmt.Errorf("could not install component on register: %w", err)
8282
}
83-
if err := comp.Mount(ctx, &comp, nil, true); err != nil {
83+
if err := comp.Mount(ctx, &comp, nil); err != nil {
8484
return Component{}, fmt.Errorf("could not install component on mount: %w", err)
8585
}
8686
return comp, nil
@@ -90,7 +90,7 @@ func Init(ctx context.Context, construct func() (Component, error)) (Component,
9090
// components sharing the same ID.
9191
func (c *Component) Self(ctx context.Context, s *live.Socket, event live.Event) {
9292
event.T = c.Event(event.T)
93-
c.Handler.Self(ctx, s, event)
93+
s.Self(ctx, event)
9494
}
9595

9696
// HandleSelf handles scoped incoming events send by a components Self function.
@@ -141,7 +141,7 @@ func defaultRegister(c *Component) error {
141141
}
142142

143143
// defaultMount is the default mount handler which does nothing.
144-
func defaultMount(ctx context.Context, c *Component, r *http.Request, connected bool) error {
144+
func defaultMount(ctx context.Context, c *Component, r *http.Request) error {
145145
return nil
146146
}
147147

page/configuration.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,17 @@ func WithRender(fn RenderHandler) ComponentConfig {
4040
// WithComponentMount set the live.Handler to mount the root component.
4141
func WithComponentMount(construct ComponentConstructor) live.HandlerConfig {
4242
return func(h *live.Handler) error {
43-
h.Mount = func(ctx context.Context, h *live.Handler, r *http.Request, s *live.Socket, connected bool) (interface{}, error) {
43+
h.Mount = func(ctx context.Context, r *http.Request, s *live.Socket) (interface{}, error) {
4444
root, err := construct(ctx, h, r, s)
4545
if err != nil {
4646
return nil, fmt.Errorf("failed to construct root component: %w", err)
4747
}
48-
if connected {
48+
if s.Connected() {
4949
if err := root.Register(&root); err != nil {
5050
return nil, err
5151
}
5252
}
53-
if err := root.Mount(ctx, &root, r, connected); err != nil {
53+
if err := root.Mount(ctx, &root, r); err != nil {
5454
return nil, err
5555
}
5656
return root, nil

page/example_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ func NewGreeter(ID string, h *live.Handler, s *live.Socket, name string) (Compon
1515
ID,
1616
h,
1717
s,
18-
WithMount(func(ctx context.Context, c *Component, r *http.Request, connected bool) error {
18+
WithMount(func(ctx context.Context, c *Component, r *http.Request) error {
1919
c.State = name
2020
return nil
2121
}),

socket.go

+28-7
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,11 @@ const (
1818

1919
// Socket describes a socket from the outside.
2020
type Socket struct {
21+
// The session for this socket.
2122
Session Session
2223

24+
handler *Handler
25+
connected bool
2326
currentRender *html.Node
2427
msgs chan Event
2528
closeSlow func()
@@ -29,10 +32,12 @@ type Socket struct {
2932
}
3033

3134
// NewSocket creates a new socket.
32-
func NewSocket(s Session) *Socket {
35+
func NewSocket(s Session, h *Handler, connected bool) *Socket {
3336
return &Socket{
34-
Session: s,
35-
msgs: make(chan Event, maxMessageBufferSize),
37+
Session: s,
38+
handler: h,
39+
connected: connected,
40+
msgs: make(chan Event, maxMessageBufferSize),
3641
}
3742
}
3843

@@ -52,7 +57,23 @@ func (s *Socket) Assign(data interface{}) {
5257
s.data = data
5358
}
5459

55-
// Send an event to this socket.
60+
// Connected returns if this socket is connected via the websocket.
61+
func (s *Socket) Connected() bool {
62+
return s.connected
63+
}
64+
65+
// Self send an event to this socket itself. Will be handled in the
66+
// handlers HandleSelf function.
67+
func (s *Socket) Self(ctx context.Context, msg Event) {
68+
s.handler.self(ctx, s, msg)
69+
}
70+
71+
// Broadcast send an event to all sockets on this same handler.
72+
func (s *Socket) Broadcast(msg Event) {
73+
s.handler.Broadcast(msg)
74+
}
75+
76+
// Send an event to this socket's client, to be handled there.
5677
func (s *Socket) Send(msg Event) {
5778
select {
5879
case s.msgs <- msg:
@@ -77,8 +98,8 @@ func (s *Socket) Redirect(u *url.URL) {
7798

7899
// mount passes this socket to the handlers mount func. This returns data
79100
// which we then set to the socket to store.
80-
func (s *Socket) mount(ctx context.Context, h *Handler, r *http.Request, connected bool) error {
81-
data, err := h.Mount(ctx, h, r, s, connected)
101+
func (s *Socket) mount(ctx context.Context, h *Handler, r *http.Request) error {
102+
data, err := h.Mount(ctx, r, s)
82103
if err != nil {
83104
return fmt.Errorf("mount error: %w", err)
84105
}
@@ -88,7 +109,7 @@ func (s *Socket) mount(ctx context.Context, h *Handler, r *http.Request, connect
88109

89110
// params passes this socket to the handlers params func. This returns data
90111
// which we then set to the socket to store.
91-
func (s *Socket) params(ctx context.Context, h *Handler, r *http.Request, connected bool) error {
112+
func (s *Socket) params(ctx context.Context, h *Handler, r *http.Request) error {
92113
for _, ph := range h.paramsHandlers {
93114
data, err := ph(ctx, s, ParamsFromRequest(r))
94115
if err != nil {

0 commit comments

Comments
 (0)