如何中断HTTP处理程序?

问题描述 投票:0回答:2

说我有一个像这样的http处理程序:

func ReallyLongFunction(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello World!")
        // run code that takes a long time here

})

如果用户在不运行后续代码的情况下刷新页面或以其他方式取消请求,有没有办法可以中断此功能,我该怎么办?

我尝试这样做:

notify := r.Context().Done()
go func() {
    <-notify
     println("Client closed the connection")
     s.downloadCleanup()
     return
}()

但是无论何时我打断之后的代码仍然可以运行。

http go handler
2个回答
2
投票
external强制拆解为该goroutine。

因此,实际中断处理的唯一方法是定期检查客户端是否消失(或者是否还有其他信号要停止处理)。

基本上,这相当于构造这样的处理程序

func ReallyLongFunction(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello World!") done := r.Context().Done() // Check wheteher we're done // do some small piece of stuff // check whether we're done // do another small piece of stuff // …rinse, repeat })

现在一种检查是否有内容写入通道,但不阻塞该操作的方法是使用“默认选择”习惯用法:

select {
    case <- done:
        // We're done
    default:
}

[并且仅当done被写入或关闭时(此情况就是这种情况),该状态执行程序才执行“ //我们完成”块中的代码,而其他情况则是default中的空块执行分支。

所以我们可以将其重构为类似的东西

func ReallyLongFunction(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello World!") done := r.Context().Done() closed := func () { select { case <- done: return true default: return false } } if closed() { return } // do some small piece of stuff if closed() { return } // do another small piece of stuff // …rinse, repeat })


0
投票
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)) }

这里是客户端,超时:

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

并且您可以使用普通的browse来检查是否不插曲。

© www.soinside.com 2019 - 2024. All rights reserved.