golang server middlerware请求取消

时间:2018-02-22 11:02:58

标签: go server middleware

我在底部的示例中创建了一个在端口3000上运行的小服务器。您可以通过" htto:// localhost:3000 / time"来访问它。整个请求包含两个中间件。首先"取消手工"和其他的#Handler"被调用 - 在4秒后响应一些虚拟数据。

解决我的问题:当我在浏览器中请求页面然后取消请求时(在4秒之前)。服务器仍在后台处理goroutine / request。我已经花了几个小时在谷歌上找到一个解决方案,但我不能围绕上下文。 (context.WithCancel())我得到了我必须创建一个陈并听取它,但这如何处理请求。那已经是goroutine,我是否必须在request / goroutine中创建另一个goroutine?还有一个问题是,我真的应该使用Context吗?还是使用cancelNotifier有一个更简单的解决方案?

也许有人可以为我和其他可能有相同理解问题的人描述它。

当浏览器取消请求时,解决方案应该是取消处理程序停止goroutine / request。

非常感谢你的时间!

package main

import (
    "log"
    "net/http"
    "time"
   "fmt"
)

func otherHandler(format string) http.Handler {
    fn := func(w http.ResponseWriter, r *http.Request) {
        time.Sleep(time.Duration(4)*time.Second)
        tm := time.Now().Format(format)
        w.Write([]byte("The time is: " + tm))
        fmt.Println("response:", "The time is: "+tm)

    }
    return http.HandlerFunc(fn)
}

func cancelHandler(h http.Handler) http.Handler {
    fn := func(w http.ResponseWriter, r *http.Request) {
        fmt.Println("start: called cancelHandler")

        h.ServeHTTP(w, r)

        fmt.Println("end: called cancelHandler")

    }
    return http.HandlerFunc(fn)
}

func main() {
    mux := http.NewServeMux()

    th := otherHandler(time.RFC1123)
    mux.Handle("/time", cancelHandler(th))

    log.Println("Listening...")
    http.ListenAndServe(":3000", mux)
}

1 个答案:

答案 0 :(得分:1)

“停止”某个功能的唯一方法就是从中返回。因此,time.Sleep不能被打断。请改用select语句:

package main

import (
    "fmt"
    "net/http"
    "time"
)

func main() {
    http.ListenAndServe(":3000", otherHandler(time.RFC1123))
}

func otherHandler(format string) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
            select {
            case <-time.After(4 * time.Second):
                    // time's up
            case <-r.Context().Done():
                    // client gave up
                    return
            }

            tm := time.Now().Format(format)
            w.Write([]byte("The time is: " + tm))
            fmt.Println("response:", "The time is: "+tm)
    }
}

通常,在战略位置检查请求上下文(或从中派生的上下文)。如果上下文被取消,请不要继续return