Skip to content

Commit a4e9fd8

Browse files
committed
add examples folder
1 parent fd7ba49 commit a4e9fd8

File tree

5 files changed

+789
-0
lines changed

5 files changed

+789
-0
lines changed

examples/basic/conn.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
//go:build ignore
2+
// +build ignore
3+
4+
package main
5+
6+
import (
7+
"fmt"
8+
"github.com/gobwas/ws"
9+
"github.com/gobwas/ws/wsutil"
10+
"github.com/gorilla/websocket"
11+
"log"
12+
"net"
13+
)
14+
15+
// GorillaConn wraps gorilla/websocket.Conn
16+
type GorillaConn struct {
17+
*websocket.Conn
18+
}
19+
20+
func (c *GorillaConn) Read() ([]byte, error) {
21+
_, msg, err := c.Conn.ReadMessage()
22+
return msg, err
23+
}
24+
25+
func (c *GorillaConn) Write(message []byte) error {
26+
fmt.Printf("[gorilla] %s\n", message)
27+
return c.Conn.WriteMessage(websocket.TextMessage, message)
28+
}
29+
30+
func (c *GorillaConn) Close() error {
31+
return c.Conn.Close()
32+
}
33+
34+
// GobwasConn wraps gobwas/ws connection
35+
type GobwasConn struct {
36+
conn net.Conn
37+
}
38+
39+
// Read reads a WebSocket message from the connection
40+
func (c *GobwasConn) Read() ([]byte, error) {
41+
msg, _, err := wsutil.ReadClientData(c.conn)
42+
if err != nil {
43+
log.Printf("WebSocket read error: %v", err)
44+
return nil, err
45+
}
46+
log.Printf("WebSocket read: %s", msg)
47+
return msg, nil
48+
}
49+
50+
// Write writes a WebSocket message to the connection
51+
func (c *GobwasConn) Write(message []byte) error {
52+
fmt.Printf("[ws] %s\n", message)
53+
err := wsutil.WriteServerMessage(c.conn, ws.OpText, message)
54+
if err != nil {
55+
log.Printf("WebSocket write error: %v", err)
56+
}
57+
return err
58+
}
59+
60+
// Close closes the WebSocket connection
61+
func (c *GobwasConn) Close() error {
62+
return c.conn.Close()
63+
}
64+
65+
// TCPConn wraps a net.Conn for raw TCP connections
66+
type TCPConn struct {
67+
conn net.Conn
68+
}
69+
70+
// Read reads data from the TCP connection
71+
func (c *TCPConn) Read() ([]byte, error) {
72+
buf := make([]byte, 1024)
73+
n, err := c.conn.Read(buf)
74+
if err != nil {
75+
return nil, err
76+
}
77+
return buf[:n], nil
78+
}
79+
80+
// Write writes data to the TCP connection
81+
func (c *TCPConn) Write(message []byte) error {
82+
fmt.Printf("[tcp] %s\n", message)
83+
_, err := c.conn.Write(message)
84+
return err
85+
}
86+
87+
// Close closes the TCP connection
88+
func (c *TCPConn) Close() error {
89+
return c.conn.Close()
90+
}

examples/basic/main.go

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
//go:build ignore
2+
// +build ignore
3+
4+
package main
5+
6+
import (
7+
"fmt"
8+
"github.com/gobwas/ws"
9+
"github.com/olekukonko/ruta"
10+
"log"
11+
"net"
12+
"sync"
13+
)
14+
15+
func main() {
16+
// Create a router
17+
router := ruta.NewRouter()
18+
router.Use(func(ctx *ruta.Frame) error {
19+
ctx.Conn.Write([]byte("Default Use\n"))
20+
return nil
21+
})
22+
23+
router.Route("hello", func(ctx *ruta.Frame) {
24+
ctx.Conn.Write([]byte("hi\n"))
25+
})
26+
27+
router.Route("say/hello", func(ctx *ruta.Frame) {
28+
ctx.Conn.Write([]byte("hello\n"))
29+
})
30+
31+
router.Route("/user/{username}", func(ctx *ruta.Frame) {
32+
username, _ := ctx.Params.Get("username")
33+
ctx.Conn.Write([]byte("Hello, " + username + "\n"))
34+
})
35+
36+
// First /welcome section
37+
router.Section("/welcome", func(r ruta.RouteBase) {
38+
r.Route("/message", func(ctx *ruta.Frame) {
39+
ctx.Conn.Write([]byte("Hello router a\n"))
40+
})
41+
})
42+
43+
// Second /welcome section with group and nested admin section
44+
router.Section("/service", func(x ruta.RouteBase) {
45+
x.Group(func(r ruta.RouteBase) {
46+
r.Use(func(ctx *ruta.Frame) error {
47+
ctx.Conn.Write([]byte("Group Use\n"))
48+
return nil
49+
})
50+
51+
r.Route("/a", func(ctx *ruta.Frame) {
52+
ctx.Conn.Write([]byte("service a\n"))
53+
})
54+
55+
r.Route("/b", func(ctx *ruta.Frame) {
56+
ctx.Conn.Write([]byte("service b\n"))
57+
})
58+
59+
// Nested admin section
60+
r.Section("/admin", func(r ruta.RouteBase) {
61+
r.Route("/", func(ctx *ruta.Frame) { // Default "/" route for /welcome/admin
62+
ctx.Conn.Write([]byte("admin base\n"))
63+
})
64+
65+
r.Group(func(r ruta.RouteBase) {
66+
r.Use(func(ctx *ruta.Frame) error {
67+
ctx.Conn.Write([]byte("Sub Group Use\n"))
68+
return nil
69+
})
70+
71+
r.Route("/yes", func(ctx *ruta.Frame) {
72+
ctx.Conn.Write([]byte("admin yes\n"))
73+
})
74+
75+
r.Route("/done", func(ctx *ruta.Frame) {
76+
ctx.Conn.Write([]byte("admin done\n"))
77+
})
78+
})
79+
})
80+
})
81+
82+
x.Route("/done", func(ctx *ruta.Frame) {
83+
ctx.Conn.Write([]byte("am done a\n"))
84+
})
85+
})
86+
87+
fmt.Println("Registered routes:")
88+
for _, route := range router.Routes() {
89+
fmt.Println(route)
90+
}
91+
92+
// Create a server with the router
93+
server := NewServer(router)
94+
95+
wg := &sync.WaitGroup{}
96+
wg.Add(2)
97+
98+
// Start TCP and WebSocket servers
99+
go handleTCP(wg, server)
100+
go handleWS(wg, server)
101+
102+
// Wait for servers to be ready
103+
wg.Wait()
104+
105+
router.Use(func(f *ruta.Frame) error {
106+
log.Printf("Command: %s", f.Command())
107+
return nil
108+
})
109+
110+
router.Section("/admin", func(r ruta.RouteBase) {
111+
r.Use(func(f *ruta.Frame) error {
112+
return fmt.Errorf("admin access required")
113+
})
114+
115+
r.Route("/shutdown", func(f *ruta.Frame) {
116+
f.Conn.Write([]byte("Shutting down\n"))
117+
})
118+
})
119+
server.Serve()
120+
}
121+
122+
func handleWS(wg *sync.WaitGroup, s *Server) {
123+
124+
// Create a WebSocket server
125+
ln, err := net.Listen("tcp", ":8080")
126+
if err != nil {
127+
log.Fatalf("Failed to listen: %v", err)
128+
}
129+
defer ln.Close()
130+
131+
fmt.Println("WebSocket server is running on :8080")
132+
wg.Done()
133+
134+
for {
135+
// Accept a new connection
136+
conn, err := ln.Accept()
137+
if err != nil {
138+
log.Printf("Failed to accept connection: %v", err)
139+
continue
140+
}
141+
142+
// Upgrade the connection to a WebSocket connection
143+
_, err = ws.Upgrade(conn)
144+
if err != nil {
145+
log.Printf("Failed to upgrade connection: %v", err)
146+
conn.Close()
147+
continue
148+
}
149+
150+
// Handle the WebSocket connection
151+
s.AddConnection(&GobwasConn{conn: conn})
152+
}
153+
}
154+
155+
func handleTCP(wg *sync.WaitGroup, s *Server) {
156+
ln, err := net.Listen("tcp", ":8081")
157+
if err != nil {
158+
fmt.Printf("Failed to start TCP server: %v\n", err)
159+
return
160+
}
161+
defer ln.Close()
162+
163+
fmt.Println("TCP server is running on :8081")
164+
wg.Done()
165+
166+
for {
167+
conn, err := ln.Accept()
168+
if err != nil {
169+
fmt.Printf("Failed to accept TCP connection: %v\n", err)
170+
continue
171+
}
172+
173+
log.Println("TCP Ready for connection")
174+
s.AddConnection(&TCPConn{conn: conn})
175+
}
176+
}

examples/basic/server.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
//go:build ignore
2+
// +build ignore
3+
4+
package main
5+
6+
import (
7+
"fmt"
8+
"github.com/olekukonko/ruta"
9+
"sync"
10+
)
11+
12+
// Server handles connection management
13+
type Server struct {
14+
router ruta.RouteBase
15+
conns []ruta.Connection // Keep this for reference, but not used in Serve()
16+
connCh chan ruta.Connection
17+
mu sync.Mutex
18+
}
19+
20+
// NewServer creates a new Server instance
21+
func NewServer(router ruta.RouteBase) *Server {
22+
return &Server{
23+
router: router,
24+
conns: make([]ruta.Connection, 0),
25+
connCh: make(chan ruta.Connection, 10), // Buffered channel to avoid blocking
26+
}
27+
}
28+
29+
// AddConnection adds a connection to the server
30+
func (s *Server) AddConnection(conn ruta.Connection) {
31+
s.mu.Lock()
32+
s.conns = append(s.conns, conn) // Optional: keep track of connections
33+
s.mu.Unlock()
34+
s.connCh <- conn // Send to channel for processing
35+
}
36+
37+
// Serve starts handling connections in a non-blocking way
38+
func (s *Server) Serve() {
39+
fmt.Printf("Serve was called\n")
40+
41+
for conn := range s.connCh {
42+
go func(c ruta.Connection) {
43+
defer c.Close()
44+
45+
for {
46+
msg, err := c.Read()
47+
if err != nil {
48+
fmt.Printf("Read error: %v\n", err)
49+
return
50+
}
51+
52+
// Log the received message
53+
fmt.Printf("Received message: %s\n", string(msg))
54+
55+
// Create a context and delegate to the router
56+
ctx := &ruta.Frame{
57+
Conn: c,
58+
Payload: ruta.NewPayload(msg),
59+
Params: ruta.NewParams(),
60+
Values: make(map[string]interface{}),
61+
}
62+
63+
// Let the router handle the message
64+
s.router.Handle(ctx)
65+
}
66+
}(conn)
67+
}
68+
}

0 commit comments

Comments
 (0)