猿问

如果请求在 http.Server 中超时,为什么在 Firefox 中会无限期地重复?

我正在 golang 中设置一个带有超时的简单服务器。当运行的处理程序花费的时间超过超时时间时,如果我使用 Firefox 请求,该请求将无限期地重复。但是,如果我使用 Postman 或curl,则 reuqest 不会重复。我想防止浏览器中出现重复循环。


我尝试手动关闭请求正文或检查上下文是否已取消,但是这些方法都不起作用。


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()

}

我希望处理程序退出并且不再重复。


守着星空守着你
浏览 104回答 1
1回答

大话西游666

根据我的理解,您面临的问题是服务器超时突然关闭底层 tcp conn 而没有编写正确的 http 响应,同时,当 firefox 检测到 conn 突然关闭时,它似乎决定重试 N 次,可能是因为它假设它遇到连接问题。我相信解决方案是使用http.Handler来控制处理程序处理持续时间,并在超时到期时返回正确的 HTTP 响应。服务器超时应该更长,并用于防止异常的客户端行为,而不是处理程序的缓慢。标准 HTTP 包为此目的提供了TimeoutHandler函数。package mainimport (    "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()}
随时随地看视频慕课网APP

相关分类

Go
我要回答