change version, add logical route groups
This commit is contained in:
parent
39d14d0025
commit
163e94d576
@ -51,7 +51,7 @@ type LuaRouter struct {
|
||||
bytecodeCache *fastcache.Cache // Cache for compiled bytecode
|
||||
|
||||
// Middleware tracking for path hierarchy
|
||||
middlewareFiles map[string][]string // path -> middleware file paths
|
||||
middlewareFiles map[string][]string // filesystem path -> middleware file paths
|
||||
|
||||
// New caching fields
|
||||
middlewareCache map[string][]byte // path -> content
|
||||
@ -72,6 +72,40 @@ type node struct {
|
||||
paramChild *node // Parameter/wildcard child
|
||||
err error // Compilation error if any
|
||||
modTime time.Time // Last modification time
|
||||
fsPath string // Original filesystem path (includes groups)
|
||||
}
|
||||
|
||||
// pathInfo holds both filesystem and URL path information
|
||||
type pathInfo struct {
|
||||
fsPath string // Filesystem path (includes groups)
|
||||
urlPath string // URL path (excludes groups)
|
||||
}
|
||||
|
||||
// parsePathWithGroups separates filesystem path from URL path
|
||||
func parsePathWithGroups(fsPath string) pathInfo {
|
||||
segments := strings.Split(strings.Trim(fsPath, "/"), "/")
|
||||
var urlSegments []string
|
||||
|
||||
for _, segment := range segments {
|
||||
if segment == "" {
|
||||
continue
|
||||
}
|
||||
// Skip group segments for URL path
|
||||
if len(segment) >= 3 && segment[0] == '(' && segment[len(segment)-1] == ')' {
|
||||
continue
|
||||
}
|
||||
urlSegments = append(urlSegments, segment)
|
||||
}
|
||||
|
||||
urlPath := "/"
|
||||
if len(urlSegments) > 0 {
|
||||
urlPath = "/" + strings.Join(urlSegments, "/")
|
||||
}
|
||||
|
||||
return pathInfo{
|
||||
fsPath: fsPath,
|
||||
urlPath: urlPath,
|
||||
}
|
||||
}
|
||||
|
||||
// NewLuaRouter creates a new LuaRouter instance
|
||||
@ -136,12 +170,13 @@ func (r *LuaRouter) buildRoutes() error {
|
||||
return err
|
||||
}
|
||||
|
||||
urlPath := "/"
|
||||
fsPath := "/"
|
||||
if relDir != "." {
|
||||
urlPath = "/" + strings.ReplaceAll(relDir, "\\", "/")
|
||||
fsPath = "/" + strings.ReplaceAll(relDir, "\\", "/")
|
||||
}
|
||||
|
||||
r.middlewareFiles[urlPath] = append(r.middlewareFiles[urlPath], path)
|
||||
// Use filesystem path for middleware (includes groups)
|
||||
r.middlewareFiles[fsPath] = append(r.middlewareFiles[fsPath], path)
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -169,19 +204,22 @@ func (r *LuaRouter) buildRoutes() error {
|
||||
return err
|
||||
}
|
||||
|
||||
urlPath := "/"
|
||||
fsPath := "/"
|
||||
if relDir != "." {
|
||||
urlPath = "/" + strings.ReplaceAll(relDir, "\\", "/")
|
||||
fsPath = "/" + strings.ReplaceAll(relDir, "\\", "/")
|
||||
}
|
||||
|
||||
pathInfo := parsePathWithGroups(fsPath)
|
||||
|
||||
// Handle index.lua files
|
||||
if fileName == "index" {
|
||||
for _, method := range []string{"GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS", "HEAD"} {
|
||||
root := r.routes[method]
|
||||
node := r.findOrCreateNode(root, urlPath)
|
||||
node := r.findOrCreateNode(root, pathInfo.urlPath)
|
||||
node.indexFile = path
|
||||
node.modTime = info.ModTime()
|
||||
r.compileWithMiddleware(node, urlPath, path)
|
||||
node.fsPath = pathInfo.fsPath
|
||||
r.compileWithMiddleware(node, pathInfo.fsPath, path)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -193,14 +231,14 @@ func (r *LuaRouter) buildRoutes() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
r.addRoute(root, urlPath, path, info.ModTime())
|
||||
r.addRoute(root, pathInfo, path, info.ModTime())
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// addRoute adds a route to the routing tree
|
||||
func (r *LuaRouter) addRoute(root *node, urlPath, handlerPath string, modTime time.Time) error {
|
||||
segments := strings.Split(strings.Trim(urlPath, "/"), "/")
|
||||
func (r *LuaRouter) addRoute(root *node, pathInfo pathInfo, handlerPath string, modTime time.Time) error {
|
||||
segments := strings.Split(strings.Trim(pathInfo.urlPath, "/"), "/")
|
||||
current := root
|
||||
|
||||
for _, segment := range segments {
|
||||
@ -230,18 +268,19 @@ func (r *LuaRouter) addRoute(root *node, urlPath, handlerPath string, modTime ti
|
||||
|
||||
current.handler = handlerPath
|
||||
current.modTime = modTime
|
||||
current.fsPath = pathInfo.fsPath
|
||||
|
||||
return r.compileWithMiddleware(current, urlPath, handlerPath)
|
||||
return r.compileWithMiddleware(current, pathInfo.fsPath, handlerPath)
|
||||
}
|
||||
|
||||
// compileWithMiddleware combines middleware and handler source, then compiles
|
||||
func (r *LuaRouter) compileWithMiddleware(n *node, urlPath, scriptPath string) error {
|
||||
func (r *LuaRouter) compileWithMiddleware(n *node, fsPath, scriptPath string) error {
|
||||
if scriptPath == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check if we need to recompile by comparing modification times
|
||||
sourceKey := r.getSourceCacheKey(urlPath, scriptPath)
|
||||
sourceKey := r.getSourceCacheKey(fsPath, scriptPath)
|
||||
needsRecompile := false
|
||||
|
||||
// Check handler modification time
|
||||
@ -258,7 +297,7 @@ func (r *LuaRouter) compileWithMiddleware(n *node, urlPath, scriptPath string) e
|
||||
|
||||
// Check middleware modification times
|
||||
if !needsRecompile {
|
||||
middlewareChain := r.getMiddlewareChain(urlPath)
|
||||
middlewareChain := r.getMiddlewareChain(fsPath)
|
||||
for _, mwPath := range middlewareChain {
|
||||
mwInfo, err := os.Stat(mwPath)
|
||||
if err != nil {
|
||||
@ -282,7 +321,7 @@ func (r *LuaRouter) compileWithMiddleware(n *node, urlPath, scriptPath string) e
|
||||
}
|
||||
|
||||
// Build combined source
|
||||
combinedSource, err := r.buildCombinedSource(urlPath, scriptPath)
|
||||
combinedSource, err := r.buildCombinedSource(fsPath, scriptPath)
|
||||
if err != nil {
|
||||
n.err = err
|
||||
return err
|
||||
@ -309,11 +348,11 @@ func (r *LuaRouter) compileWithMiddleware(n *node, urlPath, scriptPath string) e
|
||||
}
|
||||
|
||||
// buildCombinedSource builds the combined middleware + handler source
|
||||
func (r *LuaRouter) buildCombinedSource(urlPath, scriptPath string) (string, error) {
|
||||
func (r *LuaRouter) buildCombinedSource(fsPath, scriptPath string) (string, error) {
|
||||
var combinedSource strings.Builder
|
||||
|
||||
// Get middleware chain
|
||||
middlewareChain := r.getMiddlewareChain(urlPath)
|
||||
// Get middleware chain using filesystem path
|
||||
middlewareChain := r.getMiddlewareChain(fsPath)
|
||||
|
||||
// Add middleware in order
|
||||
for _, mwPath := range middlewareChain {
|
||||
@ -368,20 +407,20 @@ func (r *LuaRouter) getFileContent(path string) ([]byte, error) {
|
||||
}
|
||||
|
||||
// getSourceCacheKey generates a unique key for combined source
|
||||
func (r *LuaRouter) getSourceCacheKey(urlPath, scriptPath string) string {
|
||||
middlewareChain := r.getMiddlewareChain(urlPath)
|
||||
func (r *LuaRouter) getSourceCacheKey(fsPath, scriptPath string) string {
|
||||
middlewareChain := r.getMiddlewareChain(fsPath)
|
||||
var keyParts []string
|
||||
keyParts = append(keyParts, middlewareChain...)
|
||||
keyParts = append(keyParts, scriptPath)
|
||||
return strings.Join(keyParts, "|")
|
||||
}
|
||||
|
||||
// getMiddlewareChain returns middleware files that apply to the given path
|
||||
func (r *LuaRouter) getMiddlewareChain(urlPath string) []string {
|
||||
// getMiddlewareChain returns middleware files that apply to the given filesystem path
|
||||
func (r *LuaRouter) getMiddlewareChain(fsPath string) []string {
|
||||
var chain []string
|
||||
|
||||
// Collect middleware from root to specific path
|
||||
pathParts := strings.Split(strings.Trim(urlPath, "/"), "/")
|
||||
// Collect middleware from root to specific path using filesystem path (includes groups)
|
||||
pathParts := strings.Split(strings.Trim(fsPath, "/"), "/")
|
||||
if pathParts[0] == "" {
|
||||
pathParts = []string{}
|
||||
}
|
||||
@ -391,7 +430,7 @@ func (r *LuaRouter) getMiddlewareChain(urlPath string) []string {
|
||||
chain = append(chain, mw...)
|
||||
}
|
||||
|
||||
// Add middleware from each path level
|
||||
// Add middleware from each path level (including groups)
|
||||
currentPath := ""
|
||||
for _, part := range pathParts {
|
||||
currentPath += "/" + part
|
||||
@ -403,7 +442,7 @@ func (r *LuaRouter) getMiddlewareChain(urlPath string) []string {
|
||||
return chain
|
||||
}
|
||||
|
||||
// findOrCreateNode finds or creates a node at the given path
|
||||
// findOrCreateNode finds or creates a node at the given URL path (excludes groups)
|
||||
func (r *LuaRouter) findOrCreateNode(root *node, urlPath string) *node {
|
||||
segments := strings.Split(strings.Trim(urlPath, "/"), "/")
|
||||
current := root
|
||||
@ -467,7 +506,7 @@ func getBytecodeKey(handlerPath string) []byte {
|
||||
return uint64ToBytes(key)
|
||||
}
|
||||
|
||||
// Match finds a handler for the given method and path
|
||||
// Match finds a handler for the given method and path (URL path, excludes groups)
|
||||
func (r *LuaRouter) Match(method, path string, params *Params) (*node, bool) {
|
||||
params.Count = 0
|
||||
|
||||
@ -565,8 +604,12 @@ func (r *LuaRouter) GetRouteInfo(method, path string, params *Params) ([]byte, s
|
||||
scriptPath = n.indexFile
|
||||
}
|
||||
|
||||
urlPath := r.getNodeURLPath(n)
|
||||
if err := r.compileWithMiddleware(n, urlPath, scriptPath); err != nil {
|
||||
fsPath := n.fsPath
|
||||
if fsPath == "" {
|
||||
fsPath = "/"
|
||||
}
|
||||
|
||||
if err := r.compileWithMiddleware(n, fsPath, scriptPath); err != nil {
|
||||
return nil, handlerPath, n.err, true
|
||||
}
|
||||
|
||||
@ -602,8 +645,11 @@ func (r *LuaRouter) GetRouteInfo(method, path string, params *Params) ([]byte, s
|
||||
bytecode := r.bytecodeCache.Get(nil, bytecodeKey)
|
||||
|
||||
if len(bytecode) == 0 {
|
||||
urlPath := r.getNodeURLPath(node)
|
||||
if err := r.compileWithMiddleware(node, urlPath, scriptPath); err != nil {
|
||||
fsPath := node.fsPath
|
||||
if fsPath == "" {
|
||||
fsPath = "/"
|
||||
}
|
||||
if err := r.compileWithMiddleware(node, fsPath, scriptPath); err != nil {
|
||||
return nil, scriptPath, node.err, true
|
||||
}
|
||||
bytecode = r.bytecodeCache.Get(nil, bytecodeKey)
|
||||
@ -617,12 +663,6 @@ func (r *LuaRouter) GetRouteInfo(method, path string, params *Params) ([]byte, s
|
||||
return bytecode, scriptPath, node.err, true
|
||||
}
|
||||
|
||||
// getNodeURLPath reconstructs URL path for a node (simplified)
|
||||
func (r *LuaRouter) getNodeURLPath(node *node) string {
|
||||
// This is a simplified implementation - in practice you'd traverse up the tree
|
||||
return "/"
|
||||
}
|
||||
|
||||
// nodeForHandler finds a node by its handler path
|
||||
func (r *LuaRouter) nodeForHandler(handlerPath string) (*node, bool) {
|
||||
r.mu.RLock()
|
||||
|
@ -1,7 +1,7 @@
|
||||
package metadata
|
||||
|
||||
// Version holds the current Moonshark version
|
||||
const Version = "0.1"
|
||||
const Version = "1.0"
|
||||
|
||||
// Build time information
|
||||
var (
|
||||
|
Loading…
x
Reference in New Issue
Block a user