package middleware import ( "context" "log" "net/http" "time" "git.vinchent.xyz/vinchent/go-web/framework" ) func Timeout(d time.Duration) framework.ControllerHandler { return func(c *framework.Context) error { finish := make(chan struct{}, 1) panicChan := make(chan interface{}, 1) durationCtx, cancel := context.WithTimeout(c.BaseContext(), d) defer cancel() go func() { // Handle panic defer func() { if p := recover(); p != nil { panicChan <- p } }() // Run the next middleware or the business logic c.Next() finish <- struct{}{} }() select { case p := <-panicChan: // panic log.Println(p) c.GetResponseWriter().WriteHeader(http.StatusInternalServerError) case <-finish: // finish normally log.Println("finish") case <-durationCtx.Done(): c.SetHasTimeout() c.GetResponseWriter().Write([]byte("time out")) } return nil } }