

If we set ReadTimeout to 50ms, then the client must send both the header and the body of the request to the server within 50 milliseconds, otherwise it will time out and the server will cancel the whole process. ReadTimeout controls the timeout from Wait to Reqeust body. Let’s go back to the timeout configuration and TimeoutHandler mentioned earlier. The above is the main process of handling HTTP requests by http. After the server sends the Response, it enters the Idle phase and waits for the next HTTP request for the current connection.

So the ServeHTTP phase is divided into Request body and Response phases. The server does not read the body content of the request in the Req.headers phase, but prepares a body object for the Req object. After processing the header information of the request, http.Server knows which Handler’s ServeHTTP method to call, and thus enters the ServeHTTP phase. Server starts reading the header part of the HTTP request, which leads to the Req. In general, Go HTTP services are rarely directly external, so TLS sessions are handled by edge gateways (like Nginx), so we skip the TLS handshake phase. This corresponds to the Wait phase on the far left. Once the client establishes a TCP connection, the server starts waiting for the client to send an HTTP request. http.Server starts and calls the Accept method and waits for the client to initiate an HTTP request. This is a very important diagram because it shows the different stages of HTTP request processing by http.Server. The above configuration and TimeHandler corresponding to the role of the process as follows (from Cloudflare). In addition to these four configurations, TimeoutHandler can be used, but this needs to be generated by calling net/http.TimeoutHandler() with the following function signature.įunc TimeoutHandler(h Handler, dt time.Duration, msg string) Handler The corresponding structure of the Go HTTP server is net/http.Server, and there are four timeout-related configurations. It was very strange 🤔 I also looked into it, and eventually found the issue and commit logs, and discovered a flaw in the Go language, which I’ll share with you today. While looking at the code, I found that the Go HTTP server starts another goroutine after reading the complete HTTP request, and the goroutine tries to read another byte of content. Today, I’ll share my experience with you.
Golang http client timeout code#
I looked at the source code of the Go language HTTP service and found the cause of the deadlock. I was killed on the spot, so I rushed to find out why. When we ran another business system on AWS, because the AWS ALB configuration was different from the original nginx, we found that using only http. In fact, it was because we set the timeout control in the outermost nginx and did not expose the system to the problem. After the system went online, there had been no problems in this area, and I felt good about myself. TimeoutHandler in the outermost layer was enough.

When I was developing the framework, I did not have a deep understanding of the timeout control of the Go HTTP server. The business framework used by our department is based on the Go language net/http standard library secondary development. The system must control the timeout time of each link when providing HTTP services to the outside world, otherwise it is vulnerable to DDos attacks.
