http.TimeoutHandler возвращает, но handlerfun c продолжает работать - PullRequest
0 голосов
/ 18 марта 2020

Я тестирую http.timeoutHandler на своем go веб-сервере, я заметил, что через 3 секунды мой клиентский вызов получает сообщение "Timeout", но через 2 секунды я вижу на сервере журнал сообщений "Мой func Println». Почему TimeoutHandler не отменил мой func1?

Вот код, который я использую:

package main

import (
        "fmt"
        "io"
        "net/http"
        "time"
)

func func1(w http.ResponseWriter, req *http.Request) {
        time.Sleep(5 * time.Second)
        fmt.Println("My func Println")
        io.WriteString(w, "My func!\n")
}

func main() {
        srv := http.Server{
                Addr:         ":9000",
                WriteTimeout: 5 * time.Second,
                Handler:      http.TimeoutHandler(http.HandlerFunc(func1), 3*time.Second, "Timeout!\n"),
        }

        if err := srv.ListenAndServe(); err != nil {
                fmt.Printf("Server failed: %s\n", err)
        }
}

1 Ответ

2 голосов
/ 18 марта 2020

Да, именно так оно и должно работать.

Когда истечет время ожидания и ваша функция-обработчик все еще работает (не вернулась), контекст запроса будет отменен. Ваш обработчик несет ответственность за мониторинг канала Done для контекста и прерывает его работу при запросе отмены. Каждый обработчик работает в своей собственной программе, и операции не могут быть убиты или прерваны "извне".

Пример того, как это сделать:

func func1(w http.ResponseWriter, req *http.Request) {
    select {
    case <-time.After(5 * time.Second):
        fmt.Println("My func Println")
        io.WriteString(w, "My func!\n")
    case <-req.Context().Done():
        fmt.Println("Cancelled")
    }
}

Это будет выводить:

Cancelled

Если вы измените задержку в обработчике на 2 секунды:

case <-time.After(2 * time.Second):

Вывод будет:

My func Println

И клиент получит отправленные данные:

My func!
...