You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
93 lines
2.3 KiB
93 lines
2.3 KiB
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...) |
|
}
|
|
|