From f2103d4182acde938572c16753f8752c1f811fbf Mon Sep 17 00:00:00 2001 From: Eltrac Date: Wed, 3 Dec 2025 15:36:29 +0800 Subject: refactor: use vanilla URL.Query() instead of a custom parser Since `parser.go` only exists for splitting paths and parsing query string at the same time, it should be removed when parsing is no longer needed. Path splitting is done by a helper function inside `router.go`. --- engine.go | 4 +-- parser.go | 55 ---------------------------------------- parser_test.go | 79 ---------------------------------------------------------- router.go | 20 +++++++++------ types.go | 7 ++++-- 5 files changed, 20 insertions(+), 145 deletions(-) delete mode 100644 parser.go delete mode 100644 parser_test.go diff --git a/engine.go b/engine.go index 4c19fb2..6fc1060 100644 --- a/engine.go +++ b/engine.go @@ -33,7 +33,7 @@ func (api *Engine) DELETE(path string, h Handler) { // serve and start func (a *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) { - handler, params, query := a.router.Find(req.Method, req.URL.Path) + handler, params := a.router.Find(req.Method, req.URL.Path) if handler == nil { http.NotFound(w, req) return @@ -42,7 +42,7 @@ func (a *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) { W: w, R: req, Params: params, - Querys: query, + Querys: req.URL.Query(), }) } diff --git a/parser.go b/parser.go deleted file mode 100644 index 87b06d0..0000000 --- a/parser.go +++ /dev/null @@ -1,55 +0,0 @@ -package growel - -import ( - "fmt" - "strings" -) - -func ParsePath(path string) ([]string, map[string]string) { - var query_str string - path, query_str = extractQueryStr(path) - - parts := splitPath(path) - - if len(parts) == 0 { - return parts, map[string]string{} - } - - query := parseQueryStr(query_str) - - return parts, query -} - -func splitPath(path string) []string { - return strings.Split(strings.Trim(path, "/"), "/") -} - -func extractQueryStr(str string) (path string, querystr string) { - str_slice := strings.Split(str, "?") - leng := len(str_slice) - if leng > 2 { - fmt.Println("Error parsing path: multiple '?' found.") - // return anyway - } else if leng == 1 { - // no query string found - return str_slice[0], "" - } - return str_slice[0], str_slice[1] -} - -func parseQueryStr(str string) map[string]string { - query := make(map[string]string) - if str == "" { - return query - } - pairs := strings.Split(str, "&") - for _, pair := range pairs { - kv := strings.Split(pair, "=") - if len(kv) != 2 { - fmt.Println("Error parsing query string: invalid key-value pair.") - continue - } - query[kv[0]] = kv[1] - } - return query -} diff --git a/parser_test.go b/parser_test.go deleted file mode 100644 index cf00017..0000000 --- a/parser_test.go +++ /dev/null @@ -1,79 +0,0 @@ -package growel - -import ( - "fmt" - "reflect" - "testing" -) - -func TestRouterSplitPath(t *testing.T) { - tests := []struct { - input string - want []string - }{ - {"/", []string{""}}, - {"/hello", []string{"hello"}}, - {"/hello/world", []string{"hello", "world"}}, - {"//hello//world//", []string{"hello", "", "world"}}, - {"/hello?world=true", []string{"hello?world=true"}}, - } - - for _, tt := range tests { - got := splitPath(tt.input) - if len(got) != len(tt.want) { - t.Fatalf("splitPath(%q) length mismatch: got %v want %v", tt.input, got, tt.want) - } - for i := range got { - if got[i] != tt.want[i] { - t.Fatalf("splitPath(%q) mismatch: got %v want %v", tt.input, got, tt.want) - } - } - } -} - -func TestExtractQueryStr(t *testing.T) { - tests := []struct { - input string - want1 string - want2 string - }{ - {"", "", ""}, - {"hello", "hello", ""}, - {"user/23/", "user/23/", ""}, - {"api?str=123&yrs=23", "api", "str=123&yrs=23"}, - {"w?st?r", "w", "st"}, - {"w?str", "w", "str"}, - } - - for _, tt := range tests { - got1, got2 := extractQueryStr(tt.input) - if got1 != tt.want1 && got2 != tt.want2 { - fmt.Printf("want1: %s, got1: %s\n", tt.want1, got1) - fmt.Printf("want2: %s, got2: %s\n", tt.want2, got2) - t.Fail() - } - } -} - -func TestParseQueryStr(t *testing.T) { - tests := []struct { - input string - want map[string]string - }{ - {"str=123&yrs=23", map[string]string{ - "str": "123", - "yrs": "23", - }}, - {"str=abc", map[string]string{ - "str": "abc", - }}, - } - - for _, tt := range tests { - got := parseQueryStr(tt.input) - if !reflect.DeepEqual(got, tt.want) { - fmt.Printf("want: %s, got: %s\n", tt.want, got) - t.Fail() - } - } -} diff --git a/router.go b/router.go index c5e8933..1387474 100644 --- a/router.go +++ b/router.go @@ -11,19 +11,18 @@ func NewRouter() *Router { // Router.Add adds a route with specified method, path and handler // it splits path into segments for matching func (r *Router) Add(method string, path string, h Handler) { - parts, _ := ParsePath(path) + parts := splitPath(path) r.routes = append(r.routes, Route{method, parts, h}) } // Router.Find finds route with same HTTP method and path -// returns the handler, parameters and query +// returns the handler and dynamic parameters // // handler is a function that wraps Context // params is a map of parameters from dynamic routing -// query is a map of query parameters from URL func (r *Router) Find(method string, path string) ( - handler Handler, params map[string]string, query map[string]string) { - parts, query := ParsePath(path) + handler Handler, params map[string]string) { + parts := splitPath(path) for _, rt := range r.routes { // match HTTP method @@ -54,8 +53,15 @@ func (r *Router) Find(method string, path string) ( } } if matched { - return rt.handler, params, query + return rt.handler, params } } - return nil, nil, nil + return nil, nil +} + +/* === helpers === */ + +// splitPath splits path into segments for matching +func splitPath(path string) []string { + return strings.Split(strings.Trim(path, "/"), "/") } diff --git a/types.go b/types.go index df3e496..36e4f13 100644 --- a/types.go +++ b/types.go @@ -1,12 +1,15 @@ package growel -import "net/http" +import ( + "net/http" + "net/url" +) type Context struct { W http.ResponseWriter R *http.Request Params map[string]string - Querys map[string]string + Querys url.Values } type Handler func(c *Context) -- cgit v1.2.3