如何中断HTTP处理程序?
假设我有这样一个http处理程序:如何中断HTTP处理程序?,http,go,handler,Http,Go,Handler,假设我有这样一个http处理程序: func ReallyLongFunction(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello World!") // run code that takes a long time here // Executing dd command with cmd.Exec..., etc. }) 如果用户刷新页面或以其他方式终止请求而
func ReallyLongFunction(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello World!")
// run code that takes a long time here
// Executing dd command with cmd.Exec..., etc.
})
如果用户刷新页面或以其他方式终止请求而不运行后续代码,有没有办法中断此函数?我该如何做
我试着这样做:
notify := r.Context().Done()
go func() {
<-notify
println("Client closed the connection")
s.downloadCleanup()
return
}()
notify:=r.Context().Done()
go func(){
无法强制从该goroutine外部的任何代码中删除goroutine
因此,真正中断处理的唯一方法是定期检查客户机是否已离开(或是否有另一个停止处理的信号)
基本上,这将相当于构建类似这样的处理程序
func ReallyLongFunction(w http.ResponseWriter,r*http.Request){
Fprintf(w,“你好,世界!”)
完成:=r.Context().done()
//检查我们什么时候结束
//做一些小事情
//检查我们是否完成了
//再做一件小事
//…冲洗,重复
})
现在,检查是否有写入通道的内容,但不阻止操作的一种方法是使用“使用默认值选择”习惯用法:
选择{
case您应该从内部取消goroutine,因此对于长时间的计算任务,您可以提供检查点来停止并检查取消:
以下是服务器的测试代码,该服务器具有长计算任务和取消检查点:
package main
import (
"fmt"
"io"
"log"
"net/http"
"time"
)
func main() {
http.HandleFunc(`/`, func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
log.Println("wait a couple of seconds ...")
for i := 0; i < 10; i++ { // long calculation
select {
case <-ctx.Done():
log.Println("Client closed the connection:", ctx.Err())
return
default:
fmt.Print(".")
time.Sleep(200 * time.Millisecond) // long calculation
}
}
io.WriteString(w, `Hi`)
log.Println("Done.")
})
log.Println(http.ListenAndServe(":8081", nil))
}
您可以使用normal检查not CANCATION,或关闭、刷新、断开连接,或…,以取消。@Sterisk,是的,很抱歉混淆。是否有方法在ReallyLong函数中中断cmd.Run()或我只能检查closed()完成后?@Sterisk,按答案展开。但您没有告诉我们一个重要的细节:您的处理程序是否以某种方式将流程在运行时生成的内容传递给客户端(如将流程的输出传递给客户端)?
package main
import (
"io/ioutil"
"log"
"net/http"
"time"
)
func main() {
log.Println("HTTP GET")
client := &http.Client{
Timeout: 1 * time.Second,
}
r, err := client.Get(`http://127.0.0.1:8081/`)
if err != nil {
log.Fatal(err)
}
defer r.Body.Close()
bs, err := ioutil.ReadAll(r.Body)
if err != nil {
log.Fatal(err)
}
log.Println("HTTP Done.")
log.Println(string(bs))
}