Теперь я сделал что-то вроде этого:
func contextHandler(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithCancel(r.Context())
ctx, cancel = context.WithTimeout(ctx, config.EnvConfig.RequestTimeout)
defer cancel()
if cn, ok := w.(http.CloseNotifier); ok {
go func(done <-chan struct{}, closed <-chan bool) {
select {
case <-done:
case <-closed:
logger.Debug("message", "client connection has gone away, request will be cancelled")
cancel()
}
}(ctx.Done(), cn.CloseNotify())
}
h.ServeHTTP(w, r.WithContext(ctx))
})
}
Просьба обратить внимание на эти две строки:
ctx, cancel := context.WithCancel(r.Context())
ctx, cancel = context.WithTimeout(ctx, config.EnvConfig.RequestTimeout)
Согласно моим тестам: deliberately kill the client request
и deliberately make the request exceed the deadline
, обаработают нормально (я имею в виду, что могут получить сигнал отмены и сигнал тайм-аута, как и ожидалось), просто моя проблема: последняя функция cancel
переопределит предыдущую, возвращаемую context.WithCancel(r.Context())
, поэтому:
- Это правильный способ использовать эти два API вместе, как это?
- Есть ли необходимость использовать эти два API вместе?
Пожалуйста, помогите объяснить.