middleware/timeout: implement timeout middleware
This commit is contained in:
		@ -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
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user