]> 127.0.0.1 Git - front/.git/commitdiff
1 v0.1.20240507190308
authorqydysky <qydysky@foxmail.com>
Tue, 7 May 2024 19:00:47 +0000 (19:00 +0000)
committerqydysky <qydysky@foxmail.com>
Tue, 7 May 2024 19:00:47 +0000 (19:00 +0000)
README.md
config.go
main/main.go
main/main.json
rollRule.go

index 293cd0d3b69c0ca4b598d44bbd24fefbf92fc577..80da30a50f75d7bf4d1b0d13a6e9c5f52263999e 100755 (executable)
--- a/README.md
+++ b/README.md
@@ -25,14 +25,13 @@ config:
     - *pub*: string 公钥pem路径
     - *key*: string 私钥pem路径
 - routes: [] 路由
-    - path: string 路径
+    - path: []string 路径
     - pathAdd: bool 将客户端访问的路径附加在path上 例:/api/req => /ws => /ws/api/req
     - rollRule: string 可选
+        - `order`(按顺序)
         - `disableC_MinFirst`(禁用数较少的优先)
         - `dealingC_MinFirst`(连接数较少的优先)
         - `chosenC_MinFirst`(被选择较少的优先)
-        - `lastResDur_MinFirst`(上次响应时间较短的优先)
-        - `resDur_MinFirst`(总响应时间较短的优先)
         - (使用rand.Shuffle随机,默认)
     - reqBody: 请求后端前,请求数据过滤器
         - action: string 可选`access`、`deny`。
@@ -43,7 +42,7 @@ config:
         - name: string 后端名称,将在日志中显示
         - to: string 后端地址,例`s://www.baidu.com`,会根据客户端自动添加http or ws在地址前
         - weight: int 权重,按routes中的全部back的权重比分配,当权重为0时,将停止新请求的进入
-        - alwaysUp: bool 总是在线
+        - alwaysUp: bool 总是在线, 当只有一个后端时,默认为true
         - setting...
 
 setting:
index e43346153cffdb02982fa952d38e97a508cafb0c..4f6ecb5b49070650c48d5d208cc3338e60c4ab13 100755 (executable)
--- a/config.go
+++ b/config.go
@@ -83,7 +83,7 @@ func (t *Config) Run(ctx context.Context, logger Logger) {
 func (t *Config) SwapSign(ctx context.Context, logger Logger) {
        var add = func(k string, route *Route, logger Logger) {
                route.config = t
-               if route.Path == "" {
+               if len(route.Path) == 0 {
                        return
                }
                logger.Info(`I:`, fmt.Sprintf("%v > %v", t.Addr, k))
@@ -91,92 +91,94 @@ func (t *Config) SwapSign(ctx context.Context, logger Logger) {
 
                var logFormat = "%v%v %v %v"
 
-               t.routeP.Store(route.Path, func(w http.ResponseWriter, r *http.Request) {
-                       if len(r.RequestURI) > 8000 {
-                               logger.Warn(`W:`, fmt.Sprintf(logFormat, route.config.Addr, route.Path, "BLOCK", ErrUriTooLong))
-                               w.Header().Add(header+"Error", ErrUriTooLong.Error())
-                               w.WriteHeader(http.StatusBadRequest)
-                               return
-                       }
+               for _, routePath := range route.Path {
+                       t.routeP.Store(routePath, func(w http.ResponseWriter, r *http.Request) {
+                               if len(r.RequestURI) > 8000 {
+                                       logger.Warn(`W:`, fmt.Sprintf(logFormat, route.config.Addr, routePath, "BLOCK", ErrUriTooLong))
+                                       w.Header().Add(header+"Error", ErrUriTooLong.Error())
+                                       w.WriteHeader(http.StatusBadRequest)
+                                       return
+                               }
 
-                       if ok, e := route.Filiter.ReqUri.Match(r); e != nil {
-                               logger.Warn(`W:`, fmt.Sprintf(logFormat, route.config.Addr, route.Path, "Err", e))
-                       } else if !ok {
-                               logger.Warn(`W:`, fmt.Sprintf(logFormat, route.config.Addr, route.Path, "BLOCK", ErrPatherCheckFail))
-                               w.Header().Add(header+"Error", ErrPatherCheckFail.Error())
-                               w.WriteHeader(http.StatusForbidden)
-                               return
-                       }
+                               if ok, e := route.Filiter.ReqUri.Match(r); e != nil {
+                                       logger.Warn(`W:`, fmt.Sprintf(logFormat, route.config.Addr, routePath, "Err", e))
+                               } else if !ok {
+                                       logger.Warn(`W:`, fmt.Sprintf(logFormat, route.config.Addr, routePath, "BLOCK", ErrPatherCheckFail))
+                                       w.Header().Add(header+"Error", ErrPatherCheckFail.Error())
+                                       w.WriteHeader(http.StatusForbidden)
+                                       return
+                               }
 
-                       if ok, e := route.Filiter.ReqHeader.Match(r.Header); e != nil {
-                               logger.Warn(`W:`, fmt.Sprintf(logFormat, route.config.Addr, route.Path, "Err", e))
-                       } else if !ok {
-                               logger.Warn(`W:`, fmt.Sprintf(logFormat, route.config.Addr, route.Path, "BLOCK", ErrHeaderCheckFail))
-                               w.Header().Add(header+"Error", ErrHeaderCheckFail.Error())
-                               w.WriteHeader(http.StatusForbidden)
-                               return
-                       }
+                               if ok, e := route.Filiter.ReqHeader.Match(r.Header); e != nil {
+                                       logger.Warn(`W:`, fmt.Sprintf(logFormat, route.config.Addr, routePath, "Err", e))
+                               } else if !ok {
+                                       logger.Warn(`W:`, fmt.Sprintf(logFormat, route.config.Addr, routePath, "BLOCK", ErrHeaderCheckFail))
+                                       w.Header().Add(header+"Error", ErrHeaderCheckFail.Error())
+                                       w.WriteHeader(http.StatusForbidden)
+                                       return
+                               }
 
-                       if ok, e := route.ReqBody.Match(r); e != nil {
-                               logger.Warn(`W:`, fmt.Sprintf(logFormat, route.config.Addr, route.Path, "Err", e))
-                       } else if !ok {
-                               logger.Warn(`W:`, fmt.Sprintf(logFormat, route.config.Addr, route.Path, "BLOCK", ErrBodyCheckFail))
-                               w.Header().Add(header+"Error", ErrBodyCheckFail.Error())
-                               w.WriteHeader(http.StatusForbidden)
-                               return
-                       }
+                               if ok, e := route.ReqBody.Match(r); e != nil {
+                                       logger.Warn(`W:`, fmt.Sprintf(logFormat, route.config.Addr, routePath, "Err", e))
+                               } else if !ok {
+                                       logger.Warn(`W:`, fmt.Sprintf(logFormat, route.config.Addr, routePath, "BLOCK", ErrBodyCheckFail))
+                                       w.Header().Add(header+"Error", ErrBodyCheckFail.Error())
+                                       w.WriteHeader(http.StatusForbidden)
+                                       return
+                               }
 
-                       var backIs []*Back
+                               var backIs []*Back
 
-                       if t, e := r.Cookie("_psign_" + cookie); e == nil {
-                               if backP, aok := route.backMap.Load(t.Value); aok {
+                               if t, e := r.Cookie("_psign_" + cookie); e == nil {
+                                       if backP, aok := route.backMap.Load(t.Value); aok {
 
-                                       if ok, e := backP.(*Back).getFiliterReqUri().Match(r); e != nil {
-                                               logger.Warn(`W:`, fmt.Sprintf(logFormat, route.config.Addr, route.Path, "Err", e))
-                                       } else if ok {
-                                               aok = false
-                                       }
+                                               if ok, e := backP.(*Back).getFiliterReqUri().Match(r); e != nil {
+                                                       logger.Warn(`W:`, fmt.Sprintf(logFormat, route.config.Addr, routePath, "Err", e))
+                                               } else if ok {
+                                                       aok = false
+                                               }
 
-                                       if ok, e := backP.(*Back).getFiliterReqHeader().Match(r.Header); e != nil {
-                                               logger.Warn(`W:`, fmt.Sprintf(logFormat, route.config.Addr, route.Path, "Err", e))
-                                       } else if ok {
-                                               aok = false
-                                       }
+                                               if ok, e := backP.(*Back).getFiliterReqHeader().Match(r.Header); e != nil {
+                                                       logger.Warn(`W:`, fmt.Sprintf(logFormat, route.config.Addr, routePath, "Err", e))
+                                               } else if ok {
+                                                       aok = false
+                                               }
 
-                                       if aok {
-                                               for i := 0; i < backP.(*Back).Weight; i++ {
-                                                       backIs = append(backIs, backP.(*Back))
+                                               if aok {
+                                                       for i := 0; i < backP.(*Back).Weight; i++ {
+                                                               backIs = append(backIs, backP.(*Back))
+                                                       }
                                                }
                                        }
                                }
-                       }
 
-                       backIs = append(backIs, route.FiliterBackByRequest(r)...)
+                               backIs = append(backIs, route.FiliterBackByRequest(r)...)
 
-                       if len(backIs) == 0 {
-                               logger.Warn(`W:`, fmt.Sprintf(logFormat, route.config.Addr, route.Path, "BLOCK", ErrNoRoute))
-                               w.Header().Add(header+"Error", ErrNoRoute.Error())
-                               w.WriteHeader(http.StatusNotFound)
-                               return
-                       }
+                               if len(backIs) == 0 {
+                                       logger.Warn(`W:`, fmt.Sprintf(logFormat, route.config.Addr, routePath, "BLOCK", ErrNoRoute))
+                                       w.Header().Add(header+"Error", ErrNoRoute.Error())
+                                       w.WriteHeader(http.StatusNotFound)
+                                       return
+                               }
 
-                       var e error
-                       if strings.ToLower((r.Header.Get("Upgrade"))) == "websocket" {
-                               e = wsDealer(r.Context(), w, r, route.Path, backIs, logger, t.BlocksI)
-                       } else {
-                               e = httpDealer(r.Context(), w, r, route.Path, backIs, logger, t.BlocksI)
-                       }
-                       if e != nil {
-                               w.Header().Add(header+"Error", e.Error())
-                               if errors.Is(e, ErrHeaderCheckFail) || errors.Is(e, ErrBodyCheckFail) {
-                                       w.WriteHeader(http.StatusForbidden)
-                               } else if errors.Is(e, ErrAllBacksFail) {
-                                       w.WriteHeader(http.StatusBadGateway)
+                               var e error
+                               if strings.ToLower((r.Header.Get("Upgrade"))) == "websocket" {
+                                       e = wsDealer(r.Context(), w, r, routePath, backIs, logger, t.BlocksI)
                                } else {
-                                       t.routeP.GetConn(r).Close()
+                                       e = httpDealer(r.Context(), w, r, routePath, backIs, logger, t.BlocksI)
                                }
-                       }
-               })
+                               if e != nil {
+                                       w.Header().Add(header+"Error", e.Error())
+                                       if errors.Is(e, ErrHeaderCheckFail) || errors.Is(e, ErrBodyCheckFail) {
+                                               w.WriteHeader(http.StatusForbidden)
+                                       } else if errors.Is(e, ErrAllBacksFail) {
+                                               w.WriteHeader(http.StatusBadGateway)
+                                       } else {
+                                               t.routeP.GetConn(r).Close()
+                                       }
+                               }
+                       })
+               }
        }
 
        var del = func(k string, _ *Route, logger Logger) {
@@ -187,10 +189,12 @@ func (t *Config) SwapSign(ctx context.Context, logger Logger) {
 
        t.routeMap.Range(func(key, value any) bool {
                var exist bool
-               for k := 0; k < len(t.Routes); k++ {
-                       if key.(string) == t.Routes[k].Path {
-                               exist = true
-                               break
+               for k := 0; k < len(t.Routes) && exist == false; k++ {
+                       for _, routePath := range t.Routes[k].Path {
+                               if key.(string) == routePath {
+                                       exist = true
+                                       break
+                               }
                        }
                }
                if !exist {
@@ -201,15 +205,17 @@ func (t *Config) SwapSign(ctx context.Context, logger Logger) {
 
        for i := 0; i < len(t.Routes); i++ {
                if _, ok := t.routeMap.Load(t.Routes[i].Path); !ok {
-                       add(t.Routes[i].Path, &t.Routes[i], logger)
+                       for _, routePath := range t.Routes[i].Path {
+                               add(routePath, &t.Routes[i], logger)
+                       }
                }
                t.Routes[i].SwapSign(logger)
        }
 }
 
 type Route struct {
-       config *Config `json:"-"`
-       Path   string  `json:"path"`
+       config *Config  `json:"-"`
+       Path   []string `json:"path"`
 
        PathAdd  bool         `json:"pathAdd"`
        RollRule string       `json:"rollRule"`
@@ -225,7 +231,7 @@ func (t *Route) Id() string {
 }
 
 func (t *Route) SwapSign(logger Logger) {
-       if t.Path == "" {
+       if len(t.Path) == 0 {
                return
        }
        t.backMap.Range(func(key, value any) bool {
@@ -281,7 +287,6 @@ type Back struct {
        dealingC   int           `json:"-"`
        chosenC    int           `json:"-"`
        lastResDru time.Duration `json:"-"`
-       resDru     time.Duration `json:"-"`
 
        Name     string `json:"name"`
        To       string `json:"to"`
@@ -302,6 +307,7 @@ func (t *Back) SwapSign(logger Logger) {
        } else {
                t.verifyPeerCer, t.verifyPeerCerErr = os.ReadFile(path)
        }
+       t.AlwaysUp = len(t.route.Backs) == 1 || t.AlwaysUp
 }
 
 func (t *Back) Splicing() int {
@@ -366,7 +372,6 @@ func (t *Back) be(opT time.Time) {
        t.lock.Lock()
        t.chosenC += 1
        t.lastResDru = time.Since(opT)
-       t.resDru += t.lastResDru
        t.dealingC += 1
        t.lock.Unlock()
 }
index bcea7593a5a023386d3a0acbb2da89e5eb53684e..3029c463bb1890381aa4177e077f59f39891d68b 100755 (executable)
@@ -23,6 +23,7 @@ func main() {
 
        // 获取config路径
        configP := flag.String("c", "main.json", "config")
+       logfile := flag.String("log", "main.log", "logfile")
        testP := flag.Int("t", 0, "test port")
        _ = flag.Bool("q", false, "no log")
        _ = flag.Bool("dq", false, "no debug log")
@@ -31,6 +32,7 @@ func main() {
        // 日志初始化
        logger := plog.New(plog.Config{
                Stdout: true,
+               File:   *logfile,
                Prefix_string: map[string]struct{}{
                        `T:`: plog.On,
                        `I:`: plog.On,
index 7a5f8dab6cd8c6ae14b8d0a59abf71ea48c76140..ddec28dd3f508066f0bdaaa590bbf5303dc297b0 100755 (executable)
@@ -9,7 +9,7 @@
     },
     "routes": [
       {
-        "path": "",
+        "path": [""],
         "pathAdd": false,
         "rollRule": "",
         "reqBody": {
index fd5a6fae2913dcd141f5e7ed8faa01cedb0b2836..31acd8273a9d012296b3421d49c60534af175e89 100644 (file)
@@ -8,6 +8,8 @@ import (
 var rollRuleMap = make(map[string]func(backLink []*Back))
 
 func init() {
+       rollRuleMap[`order`] = func(backLink []*Back) {}
+
        rollRuleMap[`disable_MinFirst`] = func(backLink []*Back) {
                slices.SortStableFunc(backLink, func(a, b *Back) int {
                        return a.disableC/(a.Weight+1) - b.disableC/(b.Weight+1)
@@ -25,18 +27,6 @@ func init() {
                        return a.chosenC/(a.Weight+1) - b.chosenC/(b.Weight+1)
                })
        }
-
-       rollRuleMap[`lastResDur_MinFirst`] = func(backLink []*Back) {
-               slices.SortStableFunc(backLink, func(a, b *Back) int {
-                       return int(a.lastResDru.Milliseconds()/int64(a.Weight+1) - b.lastResDru.Milliseconds()/int64(b.Weight+1))
-               })
-       }
-
-       rollRuleMap[`resDur_MinFirst`] = func(backLink []*Back) {
-               slices.SortStableFunc(backLink, func(a, b *Back) int {
-                       return int(a.resDru.Milliseconds()/int64(a.Weight+1) - b.resDru.Milliseconds()/int64(b.Weight+1))
-               })
-       }
 }
 
 func rand_Shuffle(backLink []*Back) {