router.gno
2.24 Kb ยท 98 lines
1package mux
2
3import (
4 "net/url"
5 "strings"
6)
7
8// Router handles the routing and rendering logic.
9type Router struct {
10 routes []Handler
11 NotFoundHandler NotFoundHandler
12}
13
14// NewRouter creates a new Router instance.
15func NewRouter() *Router {
16 return &Router{
17 routes: make([]Handler, 0),
18 NotFoundHandler: defaultNotFoundHandler,
19 }
20}
21
22// Render renders the output for the given path using the registered route handler.
23func (r *Router) Render(reqPath string) string {
24 clearPath, rawQuery, _ := strings.Cut(reqPath, "?")
25 query, _ := url.ParseQuery(rawQuery)
26 reqParts := strings.Split(clearPath, "/")
27
28 for _, route := range r.routes {
29 patParts := strings.Split(route.Pattern, "/")
30 wildcard := false
31 for _, part := range patParts {
32 if part == "*" {
33 wildcard = true
34 break
35 }
36 }
37 if !wildcard && len(patParts) != len(reqParts) {
38 continue
39 }
40
41 match := true
42 for i := 0; i < len(patParts); i++ {
43 patPart := patParts[i]
44 reqPart := reqParts[i]
45
46 if patPart == "*" {
47 break
48 }
49 if strings.HasPrefix(patPart, "{") && strings.HasSuffix(patPart, "}") {
50 continue
51 }
52 if patPart != reqPart {
53 match = false
54 break
55 }
56 }
57 if match {
58 req := &Request{
59 Path: clearPath,
60 RawPath: reqPath,
61 HandlerPath: route.Pattern,
62 Query: query,
63 }
64 res := &ResponseWriter{}
65 route.Fn(res, req)
66 return res.Output()
67 }
68 }
69
70 // not found
71 req := &Request{Path: reqPath, Query: query}
72 res := &ResponseWriter{}
73 r.NotFoundHandler(res, req)
74 return res.Output()
75}
76
77// HandleFunc registers a route and its handler function.
78func (r *Router) HandleFunc(pattern string, fn HandlerFunc) {
79 route := Handler{Pattern: pattern, Fn: fn}
80 r.routes = append(r.routes, route)
81}
82
83// HandleErrFunc registers a route and its error handler function.
84func (r *Router) HandleErrFunc(pattern string, fn ErrHandlerFunc) {
85 // Convert ErrHandlerFunc to regular HandlerFunc
86 handler := func(res *ResponseWriter, req *Request) {
87 if err := fn(res, req); err != nil {
88 res.Write("Error: " + err.Error())
89 }
90 }
91
92 r.HandleFunc(pattern, handler)
93}
94
95// SetNotFoundHandler sets custom message for 404 defaultNotFoundHandler.
96func (r *Router) SetNotFoundHandler(handler NotFoundHandler) {
97 r.NotFoundHandler = handler
98}