diff --git a/go.mod b/go.mod index 6f06ac5..18ad3bd 100644 --- a/go.mod +++ b/go.mod @@ -15,6 +15,7 @@ require ( github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/go-siris/siris v7.4.0+incompatible // indirect github.com/gohugoio/hugo v0.111.3 // indirect + github.com/gorilla/schema v1.2.1 // indirect github.com/labstack/echo v3.3.10+incompatible // indirect github.com/labstack/gommon v0.4.2 // indirect github.com/mattn/go-colorable v0.1.13 // indirect diff --git a/go.sum b/go.sum index a57bd88..64e371e 100644 --- a/go.sum +++ b/go.sum @@ -144,6 +144,8 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/gorilla/schema v1.2.1 h1:tjDxcmdb+siIqkTNoV+qRH2mjYdr2hHe5MKXbp61ziM= +github.com/gorilla/schema v1.2.1/go.mod h1:Dg5SSm5PV60mhF2NFaTV1xuYYj8tV8NOPRo4FggUMnM= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= diff --git a/router.go b/router.go index bcadfb8..4951c74 100644 --- a/router.go +++ b/router.go @@ -1,6 +1,7 @@ package main import ( + // "fmt" "net/http" "reflect" "runtime" @@ -51,33 +52,33 @@ func defaultMethodNotAllowedResp(w http.ResponseWriter, req *http.Request) { } type RouteHandler struct { - function HandlerFunction - pathParams map[string]int - method HTTP_METHOD + pathParams map[string]int + route string + http_method HTTP_METHOD } -func createRouteHandler(method HTTP_METHOD) *RouteHandler { - return &RouteHandler{pathParams: make(map[string]int), method: method} +func createRouteHandler(http_method HTTP_METHOD) *RouteHandler { + return &RouteHandler{pathParams: make(map[string]int), http_method: http_method} } type SimpleRouter struct { - routeMapping map[string][]RouteHandler + routeMapping map[*RouteHandler]HandlerFunction NotFoundResp HandlerFunction MethodNotAllowedResp HandlerFunction } func CreateRouter() *SimpleRouter { router := SimpleRouter{ - routeMapping: make(map[string][]RouteHandler), + routeMapping: make(map[*RouteHandler]HandlerFunction), NotFoundResp: default404Resp, MethodNotAllowedResp: defaultMethodNotAllowedResp, } return &router } -func (r *SimpleRouter) addRoute(path string, function HandlerFunction, method HTTP_METHOD) { +func (r *SimpleRouter) addRoute(path string, function HandlerFunction, http_method HTTP_METHOD) { pathParams := make(map[string]int) - routeHandler := createRouteHandler(method) + routeHandler := createRouteHandler(http_method) if strings.Contains(path, ":") { var pathName string = "" for index, value := range strings.Split(path, "/") { @@ -95,9 +96,9 @@ func (r *SimpleRouter) addRoute(path string, function HandlerFunction, method HT if path == "" { path = "/" } - routeHandler.function = function routeHandler.pathParams = pathParams - r.routeMapping[path] = append(r.routeMapping[path], *routeHandler) + routeHandler.route = path + r.routeMapping[routeHandler] = function } func GetFunctionName(temp interface{}) string { @@ -118,7 +119,7 @@ func valueIn(i int, dict map[string]int) bool { return false } -func extractPath(urlArray []string, param RouteHandler) string { +func extractPath(urlArray []string, param *RouteHandler) string { var path string for i, value := range urlArray { if valueIn(i, param.pathParams) { @@ -129,14 +130,14 @@ func extractPath(urlArray []string, param RouteHandler) string { return path } -func getSingleSlashHandler(params []RouteHandler, urlArray []string) RouteHandler { +func getSingleSlashHandler(params []*RouteHandler, urlArray []string) (*RouteHandler, bool) { for _, routeHandlerObj := range params { if len(urlArray) == len(routeHandlerObj.pathParams) { - return routeHandlerObj + return routeHandlerObj, true } } - return RouteHandler{} + return &RouteHandler{}, false } func removeBlankStrings(array []string) []string { @@ -161,7 +162,7 @@ func mapKey(m map[string]int, value int) (key string, ok bool) { return } -func getParams(urlArray []string, param RouteHandler) map[string]string { +func getParams(urlArray []string, param *RouteHandler) map[string]string { paramValueMap := make(map[string]string) for i, value := range urlArray { @@ -180,24 +181,19 @@ func (r *SimpleRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) { pathArray := strings.Split(url, "/") pathArray = removeBlankStrings(pathArray) - var slashMap []RouteHandler - var possibleRouteHandlers []RouteHandler + var slashMap []*RouteHandler + var possibleRouteHandlers []*RouteHandler - for pathString, routeHandlers := range r.routeMapping { - if len(possibleRouteHandlers) != 0 { - break - } - if pathString == "/" { - slashMap = routeHandlers + for routeObj := range r.routeMapping { + if routeObj.route == "/" { + slashMap = append(slashMap, routeObj) continue } - for _, routeObj := range routeHandlers { - finalPath := extractPath(pathArray, routeObj) - paramValueMap := getParams(pathArray, routeObj) - if finalPath == pathString && (len(paramValueMap) == len(routeObj.pathParams)) { - possibleRouteHandlers = append(possibleRouteHandlers, routeObj) - } + finalPath := extractPath(pathArray, routeObj) + paramValueMap := getParams(pathArray, routeObj) + if finalPath == routeObj.route && (len(paramValueMap) == len(routeObj.pathParams)) { + possibleRouteHandlers = append(possibleRouteHandlers, routeObj) } } /* @@ -206,15 +202,18 @@ func (r *SimpleRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) { */ if len(possibleRouteHandlers) == 0 && len(slashMap) > 0 { - possibleRouteHandlers = append(possibleRouteHandlers, getSingleSlashHandler(slashMap, pathArray)) + routeObj, ok := getSingleSlashHandler(slashMap, pathArray) + if ok { + possibleRouteHandlers = append(possibleRouteHandlers, routeObj) + } } if len(possibleRouteHandlers) == 0 { r.NotFoundResp(w, req) return } for _, routeObj := range possibleRouteHandlers { - if routeObj.method.String() == req.Method { - routeObj.function(w, req) + if routeObj.http_method.String() == req.Method { + r.routeMapping[routeObj](w, req) return } } diff --git a/server.go b/server.go index e76efcf..75f5db2 100644 --- a/server.go +++ b/server.go @@ -49,11 +49,15 @@ func main() { r := CreateRouter() r.addRoute("/home", Home, GET) r.addRoute("/home", HomePost, POST) + r.addRoute("/home", Random, POST) + r.addRoute("/home", HomePost, POST) r.addRoute("/", Index, GET) r.addRoute("/:anyParam", Hello, POST) + r.addRoute("/:anyParam", Hello, GET) r.addRoute("/home/:somePath", HomeSomePath, PATCH) r.addRoute("/random", Random, PATCH) r.addRoute("/random/:params", RandomWithParams, DELETE) + r.addRoute("/random/:params", RandomWithParams, POST) r.addRoute("/:somePath/asdf/:nothing", HomeSomePath2, CONNECT) r.addRoute("/file/:fileName/:anotherParam", FileNotRandom, OPTIONS) r.addRoute("/file/:fileName/random/:somethingElse", FileRandom, TRACE)