Compare commits

..

No commits in common. "0aedf80727df765e337b4080cf960eeec30e2919" and "7a42f90b3f2c886faf5f385b92f48ef5019fcdc6" have entirely different histories.

5 changed files with 41 additions and 60 deletions

View File

@ -58,7 +58,7 @@ func CreateBlankConfig() *Config {
return &conf return &conf
} }
func LoadConfig(pathlike string) *VinegarHttpServlet { func LoadConfig(pathlike string) *VinegarServlet {
contents, exists := vinegarUtil.GetDiskContent(pathlike) contents, exists := vinegarUtil.GetDiskContent(pathlike)
if exists { if exists {
conf := Config{} conf := Config{}
@ -86,7 +86,7 @@ func LoadConfig(pathlike string) *VinegarHttpServlet {
} }
} }
func (e ConfigEntry) toRoute(serv *VinegarHttpServlet) { func (e ConfigEntry) toRoute(serv *VinegarServlet) {
constructor, err := getConstructorFunction(e.ConfigType) constructor, err := getConstructorFunction(e.ConfigType)
if err != nil { if err != nil {
panic(err) panic(err)

View File

@ -7,7 +7,7 @@ import (
type ( type (
ApiRoute struct { ApiRoute struct {
VinegarRoute *VinegarWebRoute VinegarRoute *VinegarRoute
HttpMethodRoutes *map[HttpMethod]VinegarHandlerFunction HttpMethodRoutes *map[HttpMethod]VinegarHandlerFunction
} }
) )
@ -25,7 +25,7 @@ const (
UNDEFINED UNDEFINED
) )
func NewApiRoute(serv *VinegarHttpServlet, pattern string) *ApiRoute { func NewApiRoute(serv *VinegarServlet, pattern string) *ApiRoute {
functionMap := make(map[HttpMethod]VinegarHandlerFunction) functionMap := make(map[HttpMethod]VinegarHandlerFunction)
ancestorRoute := NewServletRoute(pattern, createMethodHandler(&functionMap)) ancestorRoute := NewServletRoute(pattern, createMethodHandler(&functionMap))
route := ApiRoute{ route := ApiRoute{

View File

@ -25,20 +25,20 @@ type ErrorResponse struct {
} }
type ( type (
// VinegarHttpServlet is the main server struct that handles HTTP requests and routing. // VinegarServlet is the main server struct that handles HTTP requests and routing.
// It contains the TCP port to listen on, the routes to match requests against, // It contains the TCP port to listen on, the routes to match requests against,
// and a map of status code to error handling routes. // and a map of status code to error handling routes.
VinegarHttpServlet struct { VinegarServlet struct {
Port string Port string
Routes []*VinegarWebRoute Routes []*VinegarRoute
ErrorRoutes map[int]*TemplateRoute ErrorRoutes map[int]*TemplateRoute
} }
// VinegarWebRoute defines a single route in the router. // VinegarRoute defines a single route in the router.
// It contains a regex Pattern to match against the URL path, // It contains a regex Pattern to match against the URL path,
// a Handler function to call when the route matches, // a Handler function to call when the route matches,
// and an optional Cache to enable caching for the route. // and an optional Cache to enable caching for the route.
VinegarWebRoute struct { VinegarRoute struct {
Pattern *regexp.Regexp Pattern *regexp.Regexp
Handler VinegarHandlerFunction Handler VinegarHandlerFunction
Cache vinegarUtil.Cache Cache vinegarUtil.Cache
@ -47,31 +47,32 @@ type (
VinegarHandlerFunction func(w http.ResponseWriter, req *http.Request) VinegarHandlerFunction func(w http.ResponseWriter, req *http.Request)
) )
func NewServlet(port string) *VinegarHttpServlet { func NewServlet(port string) *VinegarServlet {
errs := make(map[int]*TemplateRoute) errors := make(map[int]*TemplateRoute)
srv := VinegarHttpServlet{Port: port, ErrorRoutes: errs} srv := VinegarServlet{Port: port, ErrorRoutes: errors}
return &srv return &srv
} }
func NewServletRoute(routePattern string, handleFunc VinegarHandlerFunction) *VinegarWebRoute { func NewServletRoute(routePattern string, handleFunc VinegarHandlerFunction) *VinegarRoute {
pattern := regexp.MustCompile(routePattern) pattern := regexp.MustCompile(routePattern)
route := VinegarWebRoute{Pattern: pattern, Handler: handleFunc, Cache: vinegarUtil.NewLRU(defaultLruSize)} route := VinegarRoute{Pattern: pattern, Handler: handleFunc, Cache: vinegarUtil.NewLRU(defaultLruSize)}
return &route return &route
} }
func (s *VinegarHttpServlet) AddRoute(route *VinegarWebRoute) { func (s *VinegarServlet) AddRoute(route *VinegarRoute) {
route.Announce() route.Announce()
s.Routes = append(s.Routes, route) s.Routes = append(s.Routes, route)
} }
func (s *VinegarHttpServlet) AddErrorRoute(code int, route *TemplateRoute) { func (s *VinegarServlet) AddErrorRoute(code int, route *TemplateRoute) {
route.Announce() route.Announce()
s.ErrorRoutes[code] = route s.ErrorRoutes[code] = route
} }
func (s *VinegarHttpServlet) ServeHTTP(w http.ResponseWriter, req *http.Request) { func (s *VinegarServlet) ServeHTTP(w http.ResponseWriter, req *http.Request) {
path := req.URL.Path path := req.URL.Path
for _, route := range s.Routes { for _, route := range s.Routes {
if route.Pattern.MatchString(path) { if route.Pattern.MatchString(path) {
@ -83,7 +84,7 @@ func (s *VinegarHttpServlet) ServeHTTP(w http.ResponseWriter, req *http.Request)
s.SendError(w, req, 404, "Couldn't find your content.", errors.New("failed to match route for ["+path+"]")) s.SendError(w, req, 404, "Couldn't find your content.", errors.New("failed to match route for ["+path+"]"))
} }
func (s *VinegarHttpServlet) Start() { func (s *VinegarServlet) Start() {
if len(s.Routes) < 1 { if len(s.Routes) < 1 {
log.Fatal("No routes found for server. Nothing to listen and serve.") log.Fatal("No routes found for server. Nothing to listen and serve.")
os.Exit(1) os.Exit(1)
@ -99,11 +100,11 @@ func (s *VinegarHttpServlet) Start() {
} }
func (r *VinegarWebRoute) Announce() { func (r *VinegarRoute) Announce() {
log.Printf("Added route for [%s]\n", r.Pattern.String()) log.Printf("Added route for [%s]\n", r.Pattern.String())
} }
func (s *VinegarHttpServlet) SendError(w http.ResponseWriter, req *http.Request, code int, msg string, aErr error) { func (s *VinegarServlet) SendError(w http.ResponseWriter, req *http.Request, code int, msg string, aErr error) {
fmt.Printf("[%d][%s]. Rendering template for code %d with message: %s\n", code, req.URL.Path, code, msg) fmt.Printf("[%d][%s]. Rendering template for code %d with message: %s\n", code, req.URL.Path, code, msg)
fmt.Println(aErr) fmt.Println(aErr)
tmpl, exists := s.ErrorRoutes[code] tmpl, exists := s.ErrorRoutes[code]

View File

@ -15,10 +15,10 @@ type (
FileRoute struct { FileRoute struct {
// VinegarRoute is the base route containing the URL pattern and handler. // VinegarRoute is the base route containing the URL pattern and handler.
VinegarRoute *VinegarWebRoute VinegarRoute *VinegarRoute
// srv is the VinegarHttpServlet instance that this route is attached to. // srv is the VinegarServlet instance that this route is attached to.
srv *VinegarHttpServlet srv *VinegarServlet
// fileRoot is the base file path to serve files from. // fileRoot is the base file path to serve files from.
fileRoot string fileRoot string
@ -31,7 +31,7 @@ type (
// //
//Params: //Params:
// //
//servlet - The VinegarHttpServlet instance to add the route to //servlet - The VinegarServlet instance to add the route to
// //
//urlPattern - The URL regex pattern for route to match //urlPattern - The URL regex pattern for route to match
// //
@ -39,13 +39,13 @@ type (
// //
//useCache - Whether to use caching for this route //useCache - Whether to use caching for this route
// //
// A RouteConstructor is a function that accepts a VinegarHttpServlet, urlPattern, file path, and cache option. It uses // A RouteConstructor is a function that accepts a VinegarServlet, urlPattern, file path, and cache option. It uses
// these to construct and return a FileRoute. // these to construct and return a FileRoute.
// The return value is a FileRoute that will serve the files from the given path. // The return value is a FileRoute that will serve the files from the given path.
// //
// This function signature allows encapsulating the creation of different types of FileRoutes. It is used to define // This function signature allows encapsulating the creation of different types of FileRoutes. It is used to define
// constructor functions for each file type, like NewTextRoute or NewImageRoute. // constructor functions for each file type, like NewTextRoute or NewImageRoute.
RouteConstructor func(servlet *VinegarHttpServlet, urlPattern string, pathlike string, useCache bool) *FileRoute RouteConstructor func(servlet *VinegarServlet, urlPattern string, pathlike string, useCache bool) *FileRoute
) )
// NewTextRoute creates a new FileRoute for serving text files. // NewTextRoute creates a new FileRoute for serving text files.
@ -54,7 +54,7 @@ type (
// //
// Parameters: // Parameters:
// //
// servlet - The VinegarHttpServlet instance to attach the route to. // servlet - The VinegarServlet instance to attach the route to.
// //
// urlPattern - The URL regex pattern that triggers this route. // urlPattern - The URL regex pattern that triggers this route.
// //
@ -65,14 +65,10 @@ type (
// Returns: // Returns:
// //
// A FileRoute instance configured for serving text files, added to // A FileRoute instance configured for serving text files, added to
// the provided VinegarHttpServlet. // the provided VinegarServlet.
var NewTextRoute RouteConstructor = func(servlet *VinegarHttpServlet, urlPattern string, pathlike string, useCache bool) *FileRoute { var NewTextRoute RouteConstructor = func(servlet *VinegarServlet, urlPattern string, pathlike string, useCache bool) *FileRoute {
fileRoot := filepath.Clean(pathlike)
if strings.Contains(fileRoot, "../") {
panic("Traversing the directory is not allowed, use an absolute filepath instead")
}
defaultPrune := strings.Replace(urlPattern, ".*", "", -1) defaultPrune := strings.Replace(urlPattern, ".*", "", -1)
route := FileRoute{srv: servlet, fileRoot: fileRoot, UseCache: useCache} route := FileRoute{srv: servlet, fileRoot: pathlike, UseCache: useCache}
textRouteHandler := createCompressibleFileServletFunction(&route, defaultPrune, pathlike) textRouteHandler := createCompressibleFileServletFunction(&route, defaultPrune, pathlike)
rootRoute := NewServletRoute(urlPattern, textRouteHandler) //i *still* kinda don't like this pattern rootRoute := NewServletRoute(urlPattern, textRouteHandler) //i *still* kinda don't like this pattern
route.VinegarRoute = rootRoute route.VinegarRoute = rootRoute
@ -82,13 +78,9 @@ var NewTextRoute RouteConstructor = func(servlet *VinegarHttpServlet, urlPattern
return &route return &route
} }
var NewImageRoute RouteConstructor = func(servlet *VinegarHttpServlet, urlPattern string, pathlike string, useCache bool) *FileRoute { var NewImageRoute RouteConstructor = func(servlet *VinegarServlet, urlPattern string, pathlike string, useCache bool) *FileRoute {
fileRoot := filepath.Clean(pathlike)
if strings.Contains(fileRoot, "../") {
panic("Traversing the directory is not allowed, use an absolute filepath instead")
}
defaultPrune := strings.Replace(urlPattern, ".*", "", -1) defaultPrune := strings.Replace(urlPattern, ".*", "", -1)
route := FileRoute{srv: servlet, fileRoot: fileRoot, UseCache: useCache} route := FileRoute{srv: servlet, fileRoot: pathlike, UseCache: useCache}
rootRoute := NewServletRoute(urlPattern, createUncompressedFileServletFunction(&route, defaultPrune, pathlike)) rootRoute := NewServletRoute(urlPattern, createUncompressedFileServletFunction(&route, defaultPrune, pathlike))
route.VinegarRoute = rootRoute //i *kinda* don't like this pattern route.VinegarRoute = rootRoute //i *kinda* don't like this pattern
@ -96,7 +88,7 @@ var NewImageRoute RouteConstructor = func(servlet *VinegarHttpServlet, urlPatter
return &route return &route
} }
var NewSingleFileRoute RouteConstructor = func(servlet *VinegarHttpServlet, urlPattern string, pathlike string, useCache bool) *FileRoute { var NewSingleFileRoute RouteConstructor = func(servlet *VinegarServlet, urlPattern string, pathlike string, useCache bool) *FileRoute {
route := FileRoute{ route := FileRoute{
srv: servlet, srv: servlet,
fileRoot: pathlike, fileRoot: pathlike,
@ -177,16 +169,10 @@ func createSingleFileServletFunction(route *FileRoute) VinegarHandlerFunction {
func createCompressibleFileServletFunction(route *FileRoute, basePattern string, pathlike string) VinegarHandlerFunction { func createCompressibleFileServletFunction(route *FileRoute, basePattern string, pathlike string) VinegarHandlerFunction {
var fun VinegarHandlerFunction = func(w http.ResponseWriter, req *http.Request) { var fun VinegarHandlerFunction = func(w http.ResponseWriter, req *http.Request) {
stub := strings.Replace(req.URL.Path, basePattern, "", 1) stub := strings.Replace(req.URL.Path, basePattern, "", 1)
if strings.Contains(stub, "../") {
route.srv.SendError(w, req, 403, "Forbidden", errors.New("Stop trying directory traversal"))
return
}
cachedContent, exists := route.VinegarRoute.Cache.Get(stub) cachedContent, exists := route.VinegarRoute.Cache.Get(stub)
//i don't like this logic below. we need to streamline this a lot better. it's a twisty jungle right now //i don't like this logic below. we need to streamline this a lot better. it's a twisty jungle right now
filePath := filepath.Clean(stub) resourcePath := path.Join(pathlike, filepath.Clean(stub))
pathRoot := filepath.Clean(pathlike)
resourcePath := path.Join(pathRoot, filePath)
if !exists { if !exists {
content, fileExists := util.GetDiskContent(resourcePath) content, fileExists := util.GetDiskContent(resourcePath)
@ -223,14 +209,8 @@ func createCompressibleFileServletFunction(route *FileRoute, basePattern string,
func createUncompressedFileServletFunction(route *FileRoute, basePattern string, pathlike string) VinegarHandlerFunction { func createUncompressedFileServletFunction(route *FileRoute, basePattern string, pathlike string) VinegarHandlerFunction {
var fun VinegarHandlerFunction = func(w http.ResponseWriter, req *http.Request) { var fun VinegarHandlerFunction = func(w http.ResponseWriter, req *http.Request) {
stub := strings.Replace(req.URL.Path, basePattern, "", 1) stub := filepath.Clean(strings.Replace(req.URL.Path, basePattern, "", 1))
if strings.Contains(stub, "../") { resourcePath := path.Join(pathlike, stub)
route.srv.SendError(w, req, 403, "Forbidden", errors.New("Stop trying directory traversal"))
return
}
rootPath := filepath.Clean(pathlike)
filePath := filepath.Clean(stub)
resourcePath := path.Join(rootPath, filePath)
entry, exists := route.VinegarRoute.Cache.Get(stub) entry, exists := route.VinegarRoute.Cache.Get(stub)
if !exists { if !exists {
route.VinegarRoute.Cache.Put(stub, resourcePath) route.VinegarRoute.Cache.Put(stub, resourcePath)

View File

@ -7,8 +7,8 @@ import (
type ( type (
TemplateRoute struct { TemplateRoute struct {
*VinegarWebRoute *VinegarRoute
srv *VinegarHttpServlet srv *VinegarServlet
fileRoot string fileRoot string
TemplateManager *TemplateManager TemplateManager *TemplateManager
UseCache bool UseCache bool
@ -16,12 +16,12 @@ type (
TemplateRouteHandlerFunc func(w http.ResponseWriter, r *http.Request, tm *TemplateManager) TemplateRouteHandlerFunc func(w http.ResponseWriter, r *http.Request, tm *TemplateManager)
) )
func NewTemplateRoute(servlet *VinegarHttpServlet, urlPattern string, templatePath string, componentPath string, handler TemplateRouteHandlerFunc) *TemplateRoute { func NewTemplateRoute(servlet *VinegarServlet, urlPattern string, templatePath string, componentPath string, handler TemplateRouteHandlerFunc) *TemplateRoute {
defaultPrune := strings.Replace(urlPattern, ".*", "", -1) defaultPrune := strings.Replace(urlPattern, ".*", "", -1)
tm := NewTemplateManager(templatePath, componentPath) tm := NewTemplateManager(templatePath, componentPath)
rootRoute := NewServletRoute(defaultPrune, createTemplateRouteFunction(tm, handler)) rootRoute := NewServletRoute(defaultPrune, createTemplateRouteFunction(tm, handler))
route := TemplateRoute{ route := TemplateRoute{
VinegarWebRoute: rootRoute, VinegarRoute: rootRoute,
srv: servlet, srv: servlet,
fileRoot: "", fileRoot: "",
TemplateManager: tm, TemplateManager: tm,