I wrote a timeout middleware. In this timeout middleware i created a goroutine for processing next handlers but after two seconds when timeout happens the response returns with 408 timeout status code but the goroutine runs in background and executes next handlers that are in handlers chain. So how to write a correct timeout middleware?
Timeout Middleware:
type TimeoutHandler struct {
Next http.Handler
}
func (handler *TimeoutHandler) ServeHTTP(responseWriter http.ResponseWriter, request *http.Request) {
/*if nil 'Next' handler.*/
if handler.Next == nil {
/*delegate to default serve mux.*/
handler.Next = http.DefaultServeMux
}
/*context with timeout.*/
requestContext := request.Context()
timeoutContext, cancelFunction := context.WithTimeout(requestContext, 2*time.Second)
defer cancelFunction()
/*request with new context.*/
request = request.WithContext(timeoutContext)
chanDone := make(chan bool)
go func() {
/*delegate request to `Next` handler*/
handler.Next.ServeHTTP(responseWriter, request)
chanDone <- true
}()
select {
case <-timeoutContext.Done():
/*status 408 request timeout.*/
responseWriter.WriteHeader(http.StatusRequestTimeout)
case <-chanDone:
return
}
}
These are the problems that i have:
- After timeout, next handler runs no matter what.
- If i use more handlers after timeout middleware, there is warning that says "http: multiple response.WriteHeader calls."