154 lines
4.7 KiB
Go
154 lines
4.7 KiB
Go
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)
|
|
}
|