Implement dynamic route resolution using rewrite rules
- Introduce a new `RewriteRule` type and associated functions for managing URL rewrite rules in `service/static.go`. - Add `GetRewriteRules` and `ResolveRoute` functions to facilitate the retrieval and application of rewrite rules. - Update the `sui/api/run.go` to utilize the new route resolver for handling dynamic routes when the config file is not found. - Define `RouteResolver` in `sui/core/interfaces.go` to allow for dynamic route resolution across the application.
This commit is contained in:
parent
baebefdb02
commit
19c2d6b547
3 changed files with 45 additions and 4 deletions
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"github.com/yaoapp/yao/data"
|
"github.com/yaoapp/yao/data"
|
||||||
"github.com/yaoapp/yao/service/fs"
|
"github.com/yaoapp/yao/service/fs"
|
||||||
"github.com/yaoapp/yao/share"
|
"github.com/yaoapp/yao/share"
|
||||||
|
"github.com/yaoapp/yao/sui/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AppFileServer static file server
|
// AppFileServer static file server
|
||||||
|
|
@ -24,13 +25,32 @@ var AdminRoot = ""
|
||||||
// AdminRootLen cache
|
// AdminRootLen cache
|
||||||
var AdminRootLen = 0
|
var AdminRootLen = 0
|
||||||
|
|
||||||
var rewriteRules = []rewriteRule{}
|
var rewriteRules = []RewriteRule{}
|
||||||
|
|
||||||
type rewriteRule struct {
|
// RewriteRule is a URL rewrite rule defined in app.yao
|
||||||
|
type RewriteRule struct {
|
||||||
Pattern *regexp.Regexp
|
Pattern *regexp.Regexp
|
||||||
Replacement string
|
Replacement string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetRewriteRules returns the loaded rewrite rules for use by other packages (e.g., sui/api)
|
||||||
|
func GetRewriteRules() []RewriteRule {
|
||||||
|
return rewriteRules
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResolveRoute applies rewrite rules to the given route path.
|
||||||
|
// Returns the rewritten path (with .sui suffix removed) and matched parameter values, or empty string if no rule matches.
|
||||||
|
func ResolveRoute(route string) (string, []string) {
|
||||||
|
for _, rule := range rewriteRules {
|
||||||
|
if matches := rule.Pattern.FindStringSubmatch(route); matches != nil {
|
||||||
|
rewritten := rule.Pattern.ReplaceAllString(route, rule.Replacement)
|
||||||
|
rewritten = strings.TrimSuffix(rewritten, ".sui")
|
||||||
|
return rewritten, matches
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
// SetupStatic setup static file server
|
// SetupStatic setup static file server
|
||||||
func SetupStatic() error {
|
func SetupStatic() error {
|
||||||
setupAdminRoot()
|
setupAdminRoot()
|
||||||
|
|
@ -64,12 +84,15 @@ func setupRewrite() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
rewriteRules = append(rewriteRules, rewriteRule{
|
rewriteRules = append(rewriteRules, RewriteRule{
|
||||||
Pattern: re,
|
Pattern: re,
|
||||||
Replacement: replacement,
|
Replacement: replacement,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Register the route resolver for $Backend().Call() dynamic route support
|
||||||
|
core.RouteResolver = ResolveRoute
|
||||||
}
|
}
|
||||||
|
|
||||||
// rewrite path
|
// rewrite path
|
||||||
|
|
|
||||||
|
|
@ -70,8 +70,20 @@ func Run(process *process.Process) interface{} {
|
||||||
|
|
||||||
// Get the page config
|
// Get the page config
|
||||||
cfg, err := getPageConfig(file, r.Request.DisableCache())
|
cfg, err := getPageConfig(file, r.Request.DisableCache())
|
||||||
if err != nil {
|
if err != nil && err.Error() == "The config file not found" {
|
||||||
|
// Try to resolve dynamic route via rewrite rules (e.g., /agents/yao.keeper/entry/abc123 -> /agents/yao.keeper/entry/[id])
|
||||||
|
if core.RouteResolver != nil {
|
||||||
|
if resolved, _ := core.RouteResolver(route); resolved != "" {
|
||||||
|
resolvedFile := filepath.Join("/public", strings.TrimSuffix(resolved, ".sui"))
|
||||||
|
cfg, err = getPageConfig(resolvedFile, r.Request.DisableCache())
|
||||||
|
if err == nil {
|
||||||
|
file = resolvedFile
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
if err.Error() == "The config file not found" {
|
if err.Error() == "The config file not found" {
|
||||||
exception.New("The page not found (%s)", 404, route).Throw()
|
exception.New("The page not found (%s)", 404, route).Throw()
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,12 @@ var RouteExactMatchers = map[string][][]*Matcher{}
|
||||||
// RouteRegexp the regexp for the route
|
// RouteRegexp the regexp for the route
|
||||||
var RouteRegexp = regexp.MustCompile(`([a-z0-9A-Z_\-]+)`)
|
var RouteRegexp = regexp.MustCompile(`([a-z0-9A-Z_\-]+)`)
|
||||||
|
|
||||||
|
// RouteResolver is a function that resolves a dynamic route path via rewrite rules.
|
||||||
|
// It takes an incoming route (e.g., /agents/yao.keeper/entry/abc123) and returns
|
||||||
|
// the resolved template path (e.g., /agents/yao.keeper/entry/[id]) and matched values.
|
||||||
|
// Set by the service package during initialization.
|
||||||
|
var RouteResolver func(route string) (string, []string)
|
||||||
|
|
||||||
// SUI is the interface for the SUI
|
// SUI is the interface for the SUI
|
||||||
type SUI interface {
|
type SUI interface {
|
||||||
Setting() (*Setting, error)
|
Setting() (*Setting, error)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue