如果请求在 http.Server 中超时,为什么它会在 Firefox 中无限期重复?
Why does a request repeat indefinitely in Firefox if it timed out in http.Server?
我正在 golang 中设置一个带有超时的简单服务器。当 运行 处理程序花费的时间超过超时时间时,如果我使用 Firefox 请求它,请求将无限期重复。但是,如果我使用 Postman 或 curl,reuqest 不会重复。我想防止浏览器中的重复循环。
我曾尝试手动关闭请求正文或检查上下文是否已取消,但是 none 这些方法都有效。
package main
import (
"fmt"
"net/http"
"time"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
fmt.Printf("Hello, you've requested: %s\n", r.URL.Path)
time.Sleep(time.Second * 2)
fmt.Fprintf(w, "Hello, you've requested: %s\n", r.URL.Path)
})
s := http.Server{
Addr: ":8080",
Handler: http.DefaultServeMux,
ReadTimeout: 1 * time.Second,
WriteTimeout: 1 * time.Second,
}
s.ListenAndServe()
}
我希望处理程序退出而不是重复。
据我了解,您面临的问题是服务器超时突然关闭底层 tcp conn 而没有编写正确的 http 响应,同时,当 firefox 检测到 conn 突然关闭时,它似乎决定重试 N 次,可能是因为它假设遇到连接问题。
我认为解决方案是使用 http.Handler 控制处理程序处理持续时间,并 return 在超时到期时使用正确的 HTTP 响应。
服务器超时应该更长,用于防止异常客户端行为,而不是处理程序缓慢。
标准 HTTP 包为此目的提供了一个 TimeoutHandler 函数。
package main
import (
"fmt"
"net/http"
"time"
)
func main() {
slowHandler := func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
fmt.Printf("Hello, you've requested: %s\n", r.URL.Path)
time.Sleep(time.Second * 2)
fmt.Fprintf(w, "Hello, you've requested: %s\n", r.URL.Path)
}
http.HandleFunc("/", slowHandler)
var handler http.Handler = http.DefaultServeMux
handler = http.TimeoutHandler(handler, time.Second, "processing timeout")
s := http.Server{
Addr: ":8080",
Handler: handler,
// ReadTimeout: 1 * time.Second,
// WriteTimeout: 1 * time.Second,
}
s.ListenAndServe()
}
我正在 golang 中设置一个带有超时的简单服务器。当 运行 处理程序花费的时间超过超时时间时,如果我使用 Firefox 请求它,请求将无限期重复。但是,如果我使用 Postman 或 curl,reuqest 不会重复。我想防止浏览器中的重复循环。
我曾尝试手动关闭请求正文或检查上下文是否已取消,但是 none 这些方法都有效。
package main
import (
"fmt"
"net/http"
"time"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
fmt.Printf("Hello, you've requested: %s\n", r.URL.Path)
time.Sleep(time.Second * 2)
fmt.Fprintf(w, "Hello, you've requested: %s\n", r.URL.Path)
})
s := http.Server{
Addr: ":8080",
Handler: http.DefaultServeMux,
ReadTimeout: 1 * time.Second,
WriteTimeout: 1 * time.Second,
}
s.ListenAndServe()
}
我希望处理程序退出而不是重复。
据我了解,您面临的问题是服务器超时突然关闭底层 tcp conn 而没有编写正确的 http 响应,同时,当 firefox 检测到 conn 突然关闭时,它似乎决定重试 N 次,可能是因为它假设遇到连接问题。
我认为解决方案是使用 http.Handler 控制处理程序处理持续时间,并 return 在超时到期时使用正确的 HTTP 响应。
服务器超时应该更长,用于防止异常客户端行为,而不是处理程序缓慢。
标准 HTTP 包为此目的提供了一个 TimeoutHandler 函数。
package main
import (
"fmt"
"net/http"
"time"
)
func main() {
slowHandler := func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
fmt.Printf("Hello, you've requested: %s\n", r.URL.Path)
time.Sleep(time.Second * 2)
fmt.Fprintf(w, "Hello, you've requested: %s\n", r.URL.Path)
}
http.HandleFunc("/", slowHandler)
var handler http.Handler = http.DefaultServeMux
handler = http.TimeoutHandler(handler, time.Second, "processing timeout")
s := http.Server{
Addr: ":8080",
Handler: handler,
// ReadTimeout: 1 * time.Second,
// WriteTimeout: 1 * time.Second,
}
s.ListenAndServe()
}