golang服务器中间件请求取消 [英] golang server middlerware request cancellation

查看:252
本文介绍了golang服务器中间件请求取消的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在示例的底部创建了一个运行在端口3000上的小服务器.您可以通过"htto://localhost:3000/time"访问它.整个请求包含两个中间件.第一个"cancelHandler"和第二个"otherHandler"被调用-在4秒钟后响应一些虚拟数据.

I created in the example at the bottom a little server which is running on port 3000. You can access it over "htto://localhost:3000/time". The whole Request is covered with two middlewares. First "cancelHandler" and Second "otherHandler" is called - which is responding with some dummy data after 4 seconds.

我的问题:当我在浏览器中请求该页面然后取消请求时(在4秒之前).服务器仍在后台处理goroutine/请求.我已经花了几个小时在Google上找到解决方案,但是我无法将自己的想法笼罩在上下文中. (context.WithCancel())我得到我必须创建一个chan并聆听它,但是它如何处理请求.那已经是一个goroutine,我是否必须在请求/goroutine中创建另一个goroutine?另外一个问题是,我应该真的使用Context还是使用cancelNotifier来解决问题?

To my problem: When i request the page in a browser and then cancel the request (before the 4sec). The server is still handling the goroutine/request in the background. I spent already hours to find a solution on google but i can just not wrap my head around the context. (context.WithCancel()) I get that i have to create a chan and listen to it but how does this work with the requests. thats already a goroutine, do i have to create another goroutine in the request/goroutine? Also another question is, should i really use Context for that or is there an easier solution with the cancelNotifier?

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

Maybe someone can describe it for me and others which maybe have the same understanding problem.

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

Solution should be that the cancel Handler is stopping the goroutine/request, when the browser cancels the 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)
}

推荐答案

停止"函数的唯一方法是从函数中返回.因此,time.Sleep无法中断.改用select语句:

The only way to "stop" a function is to return from it. Thus, time.Sleep cannot be interrupted. Use a select statement instead:

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.

In general, check the request context (or one that is derived from it) in strategic places. If the context is canceled, don't proceed any further and return.

这篇关于golang服务器中间件请求取消的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆