Added regexp redirect support

This commit is contained in:
Toby Chui
2024-04-04 14:24:38 +08:00
parent 05daeded37
commit 8db95dddc6
8 changed files with 175 additions and 17 deletions

View File

@@ -27,7 +27,6 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
/*
Special Routing Rules, bypass most of the limitations
*/
//Check if there are external routing rule matches.
//If yes, route them via external rr
matchedRoutingRule := h.Parent.GetMatchingRoutingRule(r)

View File

@@ -2,19 +2,25 @@ package redirection
import (
"encoding/json"
"fmt"
"log"
"os"
"path"
"path/filepath"
"regexp"
"strings"
"sync"
"imuslab.com/zoraxy/mod/info/logger"
"imuslab.com/zoraxy/mod/utils"
)
type RuleTable struct {
AllowRegex bool //Allow regular expression to be used in rule matching. Require up to O(n^m) time complexity
Logger *logger.Logger
configPath string //The location where the redirection rules is stored
rules sync.Map //Store the redirection rules for this reverse proxy instance
}
type RedirectRules struct {
@@ -24,10 +30,11 @@ type RedirectRules struct {
StatusCode int //Status Code for redirection
}
func NewRuleTable(configPath string) (*RuleTable, error) {
func NewRuleTable(configPath string, allowRegex bool) (*RuleTable, error) {
thisRuleTable := RuleTable{
rules: sync.Map{},
configPath: configPath,
AllowRegex: allowRegex,
}
//Load all the rules from the config path
if !utils.FileExists(configPath) {
@@ -77,7 +84,7 @@ func (t *RuleTable) AddRedirectRule(redirectURL string, destURL string, forwardP
}
// Convert the redirectURL to a valid filename by replacing "/" with "-" and "." with "_"
filename := strings.ReplaceAll(strings.ReplaceAll(redirectURL, "/", "-"), ".", "_") + ".json"
filename := utils.ReplaceSpecialCharacters(redirectURL) + ".json"
// Create the full file path by joining the t.configPath with the filename
filepath := path.Join(t.configPath, filename)
@@ -105,11 +112,12 @@ func (t *RuleTable) AddRedirectRule(redirectURL string, destURL string, forwardP
func (t *RuleTable) DeleteRedirectRule(redirectURL string) error {
// Convert the redirectURL to a valid filename by replacing "/" with "-" and "." with "_"
filename := strings.ReplaceAll(strings.ReplaceAll(redirectURL, "/", "-"), ".", "_") + ".json"
filename := utils.ReplaceSpecialCharacters(redirectURL) + ".json"
// Create the full file path by joining the t.configPath with the filename
filepath := path.Join(t.configPath, filename)
fmt.Println(redirectURL, filename, filepath)
// Check if the file exists
if _, err := os.Stat(filepath); os.IsNotExist(err) {
return nil // File doesn't exist, nothing to delete
@@ -145,18 +153,47 @@ func (t *RuleTable) MatchRedirectRule(requestedURL string) *RedirectRules {
// Iterate through all the keys in the rules map
var targetRedirectionRule *RedirectRules = nil
var maxMatch int = 0
t.rules.Range(func(key interface{}, value interface{}) bool {
// Check if the requested URL starts with the key as a prefix
if strings.HasPrefix(requestedURL, key.(string)) {
// This request URL matched the domain
if len(key.(string)) > maxMatch {
if t.AllowRegex {
//Regexp matching rule
matched, err := regexp.MatchString(key.(string), requestedURL)
if err != nil {
//Something wrong with the regex?
t.log("Unable to match regex", err)
return true
}
if matched {
maxMatch = len(key.(string))
targetRedirectionRule = value.(*RedirectRules)
}
} else {
//Default: prefix matching redirect
if strings.HasPrefix(requestedURL, key.(string)) {
// This request URL matched the domain
if len(key.(string)) > maxMatch {
maxMatch = len(key.(string))
targetRedirectionRule = value.(*RedirectRules)
}
}
}
return true
})
return targetRedirectionRule
}
// Log the message to log file, use STDOUT if logger not set
func (t *RuleTable) log(message string, err error) {
if t.Logger == nil {
if err == nil {
log.Println("[Redirect] " + message)
} else {
log.Println("[Redirect] " + message + ": " + err.Error())
}
} else {
t.Logger.PrintAndLog("Redirect", message, err)
}
}