diff options
| -rw-r--r-- | engine.go | 4 | ||||
| -rw-r--r-- | parser.go | 55 | ||||
| -rw-r--r-- | parser_test.go | 79 | ||||
| -rw-r--r-- | router.go | 20 | ||||
| -rw-r--r-- | types.go | 7 |
5 files changed, 20 insertions, 145 deletions
@@ -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() - } - } -} @@ -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, "/"), "/") } @@ -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) |
