0

I was going through this document related to timeouts and deadlines for HTTP servers in Go. It is a good doc, but I have one question on http.TimeoutHandler.

func slowHandler(w http.ResponseWriter, req *http.Request) {
    time.Sleep(10 * time.Second)
    log.Print("Slow API call done after 10 seconds")
    io.WriteString(w, "I am slow!\n")
}

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

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

In the doc, it is mentioned that

After a second, our TimeoutHandler will kick in, stop processing the slowHandler, and return a plain “Timeout!” message

curl request output:

# time curl localhost:8888   
*   Trying 127.0.0.1:8888...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8888 (#0)
> GET / HTTP/1.1
> Host: localhost:8888
> User-Agent: curl/7.68.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 503 Service Unavailable
< Date: Wed, 14 Dec 2022 10:19:15 GMT
< Content-Length: 9
< Content-Type: text/plain; charset=utf-8
< 
Timeout!
* Connection #0 to host localhost left intact
curl localhost:8888 -v  0.01s user 0.01s system 1% cpu 1.018 total

Indeed, the response is sent back in 1 sec.

But I also noticed that I got this message in server logs after approx 10 seconds.

2022/12/14 15:49:24 Slow API call done after 10 seconds

15:49:24 in GMT would be 10:19:24

So, I guess the slowHandler was still processing the request in the background and wasn't canceled by TimeoutHandler. It was still running in the background.

Am I understanding this correctly? And if so, then what would happen if slowHandler has an infinite loop - something like this?

func slowHandler(w http.ResponseWriter, req *http.Request) {
    for {} //infinite loop
    log.Print("infinite loop")
    io.WriteString(w, "I am slow!\n")
}

Will it keep running forever in the background?

ray an
  • 1,132
  • 3
  • 17
  • 42
  • You have to monitor the context and return. Cancelling a context does not magically ends a goroutine arbitrarily. You cannot cancel a function or goroutine from the outside, explicit cooperation is required. – icza Dec 14 '22 at 10:50

0 Answers0