diff --git a/framework/context.go b/framework/context.go index fc41c22..19961ee 100644 --- a/framework/context.go +++ b/framework/context.go @@ -97,6 +97,12 @@ func (ctx *Context) Value(key any) any { return ctx.BaseContext().Value(key) } +// Next runs the next function in the function chain +func (ctx *Context) Next() error { + // TODO + return nil +} + // }}} // {{{ Implements request functions diff --git a/framework/middleware/timeout.go b/framework/middleware/timeout.go index 15eaba6..e20d929 100644 --- a/framework/middleware/timeout.go +++ b/framework/middleware/timeout.go @@ -1,11 +1,48 @@ 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 { return nil } + 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 + } }