From: qydysky Date: Tue, 7 May 2024 19:00:47 +0000 (+0000) Subject: 1 X-Git-Tag: v0.1.20240507190308 X-Git-Url: http://127.0.0.1:8081/?a=commitdiff_plain;h=245ecef7183841235bcb997f09e5f611c34ce5f2;p=front%2F.git 1 --- diff --git a/README.md b/README.md index 293cd0d..80da30a 100755 --- 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: diff --git a/config.go b/config.go index e433461..4f6ecb5 100755 --- 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() } diff --git a/main/main.go b/main/main.go index bcea759..3029c46 100755 --- a/main/main.go +++ b/main/main.go @@ -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, diff --git a/main/main.json b/main/main.json index 7a5f8da..ddec28d 100755 --- a/main/main.json +++ b/main/main.json @@ -9,7 +9,7 @@ }, "routes": [ { - "path": "", + "path": [""], "pathAdd": false, "rollRule": "", "reqBody": { diff --git a/rollRule.go b/rollRule.go index fd5a6fa..31acd82 100644 --- a/rollRule.go +++ b/rollRule.go @@ -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) {