Added load balancer module

- Added load balancer module wip
- Updated geoipv4
- Reduced uptime timeout to 5 sec
- Optimized rate limit implementation
- Fixed minor UI bug in stream proxy
This commit is contained in:
Toby Chui
2024-06-19 00:38:48 +08:00
parent 704980d4f8
commit 973d0b3372
13 changed files with 3013 additions and 2207 deletions

View File

@@ -17,7 +17,7 @@ import (
// return upstream header and downstream header key-value pairs
// if the header is expected to be deleted, the value will be set to empty string
func (ept *ProxyEndpoint) SplitInboundOutboundHeaders() ([][]string, [][]string) {
if len(ept.UserDefinedHeaders) == 0 {
if len(ept.UserDefinedHeaders) == 0 && ept.HSTSMaxAge == 0 && !ept.EnablePermissionPolicyHeader {
//Early return if there are no defined headers
return [][]string{}, [][]string{}
}

View File

@@ -0,0 +1,60 @@
package loadbalance
import (
"imuslab.com/zoraxy/mod/geodb"
"imuslab.com/zoraxy/mod/info/logger"
"imuslab.com/zoraxy/mod/uptime"
)
/*
Load Balancer
Handleing load balance request for upstream destinations
*/
type BalancePolicy int
const (
BalancePolicy_RoundRobin BalancePolicy = 0 //Round robin, will ignore upstream if down
BalancePolicy_Fallback BalancePolicy = 1 //Fallback only. Will only switch to next node if the first one failed
BalancePolicy_Random BalancePolicy = 2 //Random, randomly pick one from the list that is online
BalancePolicy_GeoRegion BalancePolicy = 3 //Use the one defined for this geo-location, when down, pick the next avaible node
)
type LoadBalanceRule struct {
Upstreams []string //Reverse proxy upstream servers
LoadBalancePolicy BalancePolicy //Policy in deciding which target IP to proxy
UseRegionLock bool //If this is enabled with BalancePolicy_Geo, when the main site failed, it will not pick another node
UseStickySession bool //Use sticky session, if you are serving EU countries, make sure to add the "Do you want cookie" warning
parent *RouteManager
}
type Options struct {
Geodb *geodb.Store //GeoIP resolver for checking incoming request origin country
UptimeMonitor *uptime.Monitor //For checking if the target is online, this might be nil when the module starts
}
type RouteManager struct {
Options Options
Logger *logger.Logger
}
// Create a new load balance route manager
func NewRouteManager(options *Options, logger *logger.Logger) *RouteManager {
newManager := RouteManager{
Options: *options,
Logger: logger,
}
logger.PrintAndLog("INFO", "Load Balance Route Manager started", nil)
return &newManager
}
func (b *LoadBalanceRule) GetProxyTargetIP() {
}
// Print debug message
func (m *RouteManager) debugPrint(message string, err error) {
m.Logger.PrintAndLog("LoadBalancer", message, err)
}

View File

@@ -1,7 +1,7 @@
package redirection
import (
"log"
"errors"
"net/http"
"strings"
)
@@ -52,7 +52,7 @@ func (t *RuleTable) HandleRedirect(w http.ResponseWriter, r *http.Request) int {
//Invalid usage
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("500 - Internal Server Error"))
log.Println("Target request URL do not have matching redirect rule. Check with IsRedirectable before calling HandleRedirect!")
t.log("Target request URL do not have matching redirect rule. Check with IsRedirectable before calling HandleRedirect!", errors.New("invalid usage"))
return 500
}
}

View File

@@ -30,11 +30,12 @@ type RedirectRules struct {
StatusCode int //Status Code for redirection
}
func NewRuleTable(configPath string, allowRegex bool) (*RuleTable, error) {
func NewRuleTable(configPath string, allowRegex bool, logger *logger.Logger) (*RuleTable, error) {
thisRuleTable := RuleTable{
rules: sync.Map{},
configPath: configPath,
AllowRegex: allowRegex,
Logger: logger,
}
//Load all the rules from the config path
if !utils.FileExists(configPath) {
@@ -67,7 +68,7 @@ func NewRuleTable(configPath string, allowRegex bool) (*RuleTable, error) {
//Map the rules into the sync map
for _, rule := range rules {
log.Println("Redirection rule added: " + rule.RedirectURL + " -> " + rule.TargetURL)
thisRuleTable.log("Redirection rule added: "+rule.RedirectURL+" -> "+rule.TargetURL, nil)
thisRuleTable.rules.Store(rule.RedirectURL, rule)
}
@@ -92,7 +93,7 @@ func (t *RuleTable) AddRedirectRule(redirectURL string, destURL string, forwardP
// Create a new file for writing the JSON data
file, err := os.Create(filepath)
if err != nil {
log.Printf("Error creating file %s: %s", filepath, err)
t.log("Error creating file "+filepath, err)
return err
}
defer file.Close()
@@ -100,7 +101,7 @@ func (t *RuleTable) AddRedirectRule(redirectURL string, destURL string, forwardP
// Encode the RedirectRules object to JSON and write it to the file
err = json.NewEncoder(file).Encode(newRule)
if err != nil {
log.Printf("Error encoding JSON to file %s: %s", filepath, err)
t.log("Error encoding JSON to file "+filepath, err)
return err
}
@@ -125,7 +126,7 @@ func (t *RuleTable) DeleteRedirectRule(redirectURL string) error {
// Delete the file
if err := os.Remove(filepath); err != nil {
log.Printf("Error deleting file %s: %s", filepath, err)
t.log("Error deleting file "+filepath, err)
return err
}