package rest import ( "crypto/tls" "git.diulo.com/mogfee/kit/rest/chain" "git.diulo.com/mogfee/kit/rest/httpx" "git.diulo.com/mogfee/kit/rest/internal" "net/http" "time" ) type engine struct { conf RestConf routes []featureRoutes timeout time.Duration chain chain.Chain middlewares []Middleware tlsConfig *tls.Config } func newEngine(c RestConf) *engine { srv := &engine{ conf: c, timeout: time.Duration(c.Timeout), middlewares: make([]Middleware, 0), } return srv } func (n *engine) addRoutes(r featureRoutes) { n.routes = append(n.routes, r) if r.timeout > n.timeout { n.timeout = r.timeout } } func (n *engine) bindRoutes(router httpx.Router) error { for _, fr := range n.routes { for _, route := range fr.routes { if err := n.bindRoute(fr, router, route); err != nil { return err } } } return nil } func (n *engine) bindRoute(fr featureRoutes, router httpx.Router, route Route) error { chn := n.chain if chn == nil { chn = n.buildChainWithNativeMiddlewares(fr, route) } for _, middleware := range n.middlewares { chn = chn.Append(convertMiddleware(middleware)) } handle := chn.ThenFunc(route.Handler) return router.Handle(route.Method, route.Path, handle) } func (n *engine) buildChainWithNativeMiddlewares(fr featureRoutes, route Route) chain.Chain { chn := chain.New() return chn } func convertMiddleware(ware Middleware) func(http.Handler) http.Handler { return func(handler http.Handler) http.Handler { return ware(handler.ServeHTTP) } } func (n *engine) start(router httpx.Router) error { err := n.bindRoutes(router) if err != nil { return err } if len(n.conf.CertFile) == 0 && len(n.conf.KeyFile) == 0 { return internal.StartHttp(n.conf.Host, n.conf.Port, router, n.withTimeout()) } return internal.StartHttps(n.conf.Host, n.conf.Port, n.conf.CertFile, n.conf.KeyFile, router, func(svr *http.Server) { if n.tlsConfig != nil { svr.TLSConfig = n.tlsConfig } }, n.withTimeout()) } func (n *engine) withTimeout() internal.StartOption { return func(svr *http.Server) { timeout := n.timeout if timeout > 0 { svr.ReadTimeout = 4 * timeout / 5 svr.WriteTimeout = 11 * timeout / 10 } } } func (n *engine) use(middleware ...Middleware) { n.middlewares = append(n.middlewares, middleware...) }