Deal(ctx context.Context, w http.ResponseWriter, r *http.Request, routePath string, chosenBack *Back, logger Logger, blocksi pslice.BlocksI[byte]) error
}
- for i := 0; i < len(backIs) && errors.Is(e, ErrAllBacksFail); i++ {
+ for i := 0; i < len(backIs); i++ {
if !backIs[i].IsLive() {
continue
}
} else {
e = component2.Get[reqDealer]("http").Deal(r.Context(), w, r, routePath, backIs[i], logger, t.BlocksI)
}
+
+ // no err
+ if e == nil {
+ break
+ }
+
+ // some err can retry
+ if v, ok := e.(ErrCanRetry); !ok || !v.CanRetry {
+ break
+ }
}
if e != nil {
}
}
+type ErrCanRetry struct {
+ error
+ CanRetry bool
+}
+
+func MarkRetry(e error) error {
+ return ErrCanRetry{
+ error: e,
+ CanRetry: true,
+ }
+}
+
type Route struct {
config *Config `json:"-"`
Path []string `json:"path"`
if e != nil {
logger.Warn(`W:`, fmt.Sprintf(logFormat, r.RemoteAddr, chosenBack.route.config.Addr, routePath, chosenBack.Name, "Err", e, time.Since(opT)))
chosenBack.Disable()
- return ErrReqCreFail
+ return MarkRetry(ErrReqCreFail)
}
- if e := copyHeader(r.Header, req.Header, chosenBack.getDealerReqHeader()); e != nil {
- logger.Warn(`W:`, fmt.Sprintf(logFormat, r.RemoteAddr, chosenBack.route.config.Addr, routePath, chosenBack.Name, "BLOCK", e, time.Since(opT)))
- return ErrDealReqHeader
- }
+ // if e :=
+ copyHeader(r.Header, req.Header, chosenBack.getDealerReqHeader())
+ // ; e != nil {
+ // logger.Warn(`W:`, fmt.Sprintf(logFormat, r.RemoteAddr, chosenBack.route.config.Addr, routePath, chosenBack.Name, "BLOCK", e, time.Since(opT)))
+ // return ErrDealReqHeader
+ // }
customTransport := http.DefaultTransport.(*http.Transport).Clone()
if e != nil && !errors.Is(e, ErrRedirect) && !errors.Is(e, context.Canceled) {
logger.Warn(`W:`, fmt.Sprintf(logFormat, r.RemoteAddr, chosenBack.route.config.Addr, routePath, chosenBack.Name, "Err", e, time.Since(opT)))
chosenBack.Disable()
- return ErrResFail
+ return MarkRetry(ErrResFail)
}
if chosenBack.getErrToSec() != 0 && time.Since(opT).Seconds() > chosenBack.getErrToSec() {
}
if resp == nil {
- return ErrResFail
+ return MarkRetry(ErrResFail)
}
if ok, e := chosenBack.getFiliterResHeader().Match(resp.Header); e != nil {
} else if !ok {
logger.Warn(`W:`, fmt.Sprintf(logFormat, r.RemoteAddr, chosenBack.route.config.Addr, routePath, chosenBack.Name, "BLOCK", ErrHeaderCheckFail, time.Since(opT)))
w.Header().Add(header+"Error", ErrHeaderCheckFail.Error())
- return ErrHeaderCheckFail
+ return MarkRetry(ErrHeaderCheckFail)
}
logger.Debug(`T:`, fmt.Sprintf(logFormat, r.RemoteAddr, chosenBack.route.config.Addr, routePath, chosenBack.Name, r.Method, r.RequestURI, time.Since(opT)))
w.Header().Add(header+"Info", cookie+";"+chosenBack.Name)
- if e := copyHeader(resp.Header, w.Header(), chosenBack.getDealerResHeader()); e != nil {
- logger.Warn(`W:`, fmt.Sprintf(logFormat, r.RemoteAddr, chosenBack.route.config.Addr, routePath, chosenBack.Name, "BLOCK", e, time.Since(opT)))
- return ErrDealResHeader
- }
+ // if e :=
+ copyHeader(resp.Header, w.Header(), chosenBack.getDealerResHeader())
+ // ; e != nil {
+ // logger.Warn(`W:`, fmt.Sprintf(logFormat, r.RemoteAddr, chosenBack.route.config.Addr, routePath, chosenBack.Name, "BLOCK", e, time.Since(opT)))
+ // return ErrDealResHeader
+ // }
w.WriteHeader(resp.StatusCode)
"fmt"
"net/http"
"net/url"
+ "os"
"time"
_ "unsafe"
path := chosenBack.To
if chosenBack.PathAdd() {
if s, e := url.PathUnescape(r.URL.Path); e != nil {
- logger.Warn(`W:`, fmt.Sprintf(logFormat, r.RemoteAddr, chosenBack.route.config.Addr, routePath, chosenBack.Name, "BLOCK", e, time.Since(opT)))
+ logger.Warn(`W:`, fmt.Sprintf(logFormat, r.RemoteAddr, chosenBack.route.config.Addr, routePath, chosenBack.Name, "Err", e, time.Since(opT)))
return ErrDealReqUri
} else {
path += s
}
if !pfile.New(path, 0, true).IsExist() {
- return ErrReqDoFail
+ return MarkRetry(os.ErrNotExist)
}
- if e := copyHeader(http.Header{}, w.Header(), chosenBack.getDealerResHeader()); e != nil {
- logger.Warn(`W:`, fmt.Sprintf(logFormat, r.RemoteAddr, chosenBack.route.config.Addr, routePath, chosenBack.Name, "BLOCK", e, time.Since(opT)))
- return ErrDealResHeader
- }
+ // if e :=
+ copyHeader(http.Header{}, w.Header(), chosenBack.getDealerResHeader())
+ // ; e != nil {
+ // logger.Warn(`W:`, fmt.Sprintf(logFormat, r.RemoteAddr, chosenBack.route.config.Addr, routePath, chosenBack.Name, "BLOCK", e, time.Since(opT)))
+ // return ErrDealResHeader
+ // }
logger.Debug(`T:`, fmt.Sprintf(logFormat, r.RemoteAddr, chosenBack.route.config.Addr, routePath, chosenBack.Name, r.Method, r.RequestURI, time.Since(opT)))
return
}
-func copyHeader(s, t http.Header, app []dealer.HeaderDealer) error {
+func copyHeader(s, t http.Header, app []dealer.HeaderDealer) {
sm := (map[string][]string)(s)
tm := (map[string][]string)(t)
for k, v := range sm {
default:
}
}
- return nil
}
var cookie = fmt.Sprintf("%p", &struct{}{})
reqHeader := make(http.Header)
- if e := copyHeader(r.Header, reqHeader, chosenBack.getDealerReqHeader()); e != nil {
- logger.Warn(`W:`, fmt.Sprintf(errFormat, r.RemoteAddr, chosenBack.route.config.Addr, routePath, chosenBack.Name, e, time.Since(opT)))
- return ErrDealReqHeader
- }
+ // if e :=
+ copyHeader(r.Header, reqHeader, chosenBack.getDealerReqHeader())
+ // ; e != nil {
+ // logger.Warn(`W:`, fmt.Sprintf(errFormat, r.RemoteAddr, chosenBack.route.config.Addr, routePath, chosenBack.Name, e, time.Since(opT)))
+ // return ErrDealReqHeader
+ // }
var e error
conn, resp, e = DialContext(ctx, url, reqHeader, chosenBack)
if e != nil && !errors.Is(e, context.Canceled) {
logger.Warn(`W:`, fmt.Sprintf(errFormat, r.RemoteAddr, chosenBack.route.config.Addr, routePath, chosenBack.Name, e, time.Since(opT)))
chosenBack.Disable()
- return ErrResFail
+ return MarkRetry(ErrResFail)
}
if chosenBack.getErrToSec() != 0 && time.Since(opT).Seconds() > chosenBack.getErrToSec() {
// }
if conn == nil || resp == nil {
- return ErrResFail
+ return MarkRetry(ErrResFail)
}
if pctx.Done(r.Context()) {
} else if !ok {
logger.Warn(`W:`, fmt.Sprintf(errFormat, r.RemoteAddr, chosenBack.route.config.Addr, routePath, chosenBack.Name, ErrHeaderCheckFail, time.Since(opT)))
w.Header().Add(header+"Error", ErrHeaderCheckFail.Error())
- return ErrHeaderCheckFail
+ return MarkRetry(ErrHeaderCheckFail)
}
logger.Debug(`T:`, fmt.Sprintf("%v > %v > %v ws ok %v", chosenBack.route.config.Addr, routePath, chosenBack.Name, time.Since(opT)))
defer conn.Close()
resHeader := make(http.Header)
- if e := copyHeader(resp.Header, resHeader, chosenBack.getDealerResHeader()); e != nil {
- logger.Warn(`W:`, fmt.Sprintf(errFormat, r.RemoteAddr, chosenBack.route.config.Addr, routePath, chosenBack.Name, e, time.Since(opT)))
- return ErrDealResHeader
- }
+ // if e :=
+ copyHeader(resp.Header, resHeader, chosenBack.getDealerResHeader())
+ // ; e != nil {
+ // logger.Warn(`W:`, fmt.Sprintf(errFormat, r.RemoteAddr, chosenBack.route.config.Addr, routePath, chosenBack.Name, e, time.Since(opT)))
+ // return ErrDealResHeader
+ // }
if req, e := Upgrade(w, r, resHeader); e != nil {
- return ErrResDoFail
+ return MarkRetry(ErrResDoFail)
} else {
defer req.Close()