package servlet import ( "encoding/json" "errors" "geniuscartel.xyz/vinegar/vinegarUtil" "log" "net/http" "regexp" ) type ( // VinegarWebRouter is the router struct that handles routing HTTP requests. // // It contains a single field: // // Routes - A slice of pointers to VinegarWebRoute structs. Each route in // this slice is checked to see if it matches the incoming request path. // // When a request comes in, the router iterates through the Routes and executes // the handler of the first route that matches the path. // // Custom routes can be added using the AddRoute method. The routes will be // checked in the order they are added. // // Example Usage: // // router := VinegarWebRouter{} // route := VinegarWebRoute{ // //...initialize route // } // // router.AddRoute(&route) // Adds route to router // // router.RouteRequest(w, r) // Handle request by matching against routes VinegarWebRouter struct { Routes []*VinegarWebRoute } // VinegarWebRoute defines a single route in the router. // It contains the following fields: // //Pattern - A regexp.Regexp instance that matches against the request URL path. // //Handler - A VinegarHandlerFunction to call when the route matches a request. // //Cache - An optional vinegarUtil.Cache instance to enable caching for this route. // //VinegarWebRoute is used to define custom routes to handle requests in the //VinegarWebRouter. Routes should be added to the router using: // // router.AddRoute(route) // //The router will match incoming requests against route patterns in order. //When a match is found, the Handler is executed to handle the request. // //Example usage: // // route := VinegarWebRoute{ // Pattern: regexp.MustCompile("/users"), // Handler: myUserHandler, // } // router.AddRoute(&route) VinegarWebRoute struct { Pattern *regexp.Regexp Handler VinegarHandlerFunction Cache vinegarUtil.Cache } ) // AddRoute adds a new route to the router. // // It accepts a pointer to a VinegarWebRoute struct to add as a parameter. // // It calls the Announce() method on the route to print a message that the // route was added. // // It appends the route to the Routes slice field of the VinegarWebRouter. // // This allows custom routes to be registered with the router. The routes // will be checked in order when handling incoming requests. // // Parameters: // route: Pointer to a VinegarWebRoute instance to add as a route. func (s *VinegarWebRouter) AddRoute(route *VinegarWebRoute) { route.Announce() s.Routes = append(s.Routes, route) } // RouteRequest routes an incoming HTTP request to the matching handler // function for that request path. // // It takes an http.ResponseWriter and *http.Request as parameters. // // It iterates through the router's routes and tries to match the request // path against the route patterns. If a match is found, it executes the // route's handler function, prints the match, and returns nil. // // If no match is found, it calls the notFoundHandler helper and returns // an error. // // Parameters: // w: The http.ResponseWriter used to send the response back to the client // req: The *http.Request containing details about the incoming request // // Returns: // error: Any error encountered while routing the request, otherwise nil func (r *VinegarWebRouter) RouteRequest(w http.ResponseWriter, req *http.Request) error { path := req.URL.Path for _, route := range r.Routes { if route.Pattern.MatchString(path) { log.Printf("SERVING: [%s]=>{%s}\n", path, route.Pattern.String()) go route.Handler(w, req) return nil } } notFoundHandler(w, req) return errors.New("failed to match route for [" + path + "]") } // notFoundHandler handles requests for unknown routes by returning a 404 Not Found response. // // It takes an http.ResponseWriter and *http.Request as parameters. // // It sets the response status code to 404. // // It creates an ErrorResponse struct with a 404 status code and error message. // // It marshals the ErrorResponse to JSON. // // It sets the Content-Type header to application/json. // // It writes the JSON error response to the http.ResponseWriter. // // This provides a consistent JSON error response when no matching route is found. // // Parameters: // w: The http.ResponseWriter used to send the response back to the client. // r: The *http.Request that could not be routed. func notFoundHandler(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNotFound) errorResponse := ErrorResponse{ Code: http.StatusNotFound, Message: "The requested resource could not be found.", } jsonBytes, _ := json.Marshal(errorResponse) w.Header().Add("Content-Type", "application/json") w.Write(jsonBytes) }