猿问

速率限制特定端点

我是 GoLang 的新手,正在开发我的第一个 API。我有两个端点,我只想对其中一个端点进行速率限制。我找到了一个有用的教程来帮助我入门,我的方法基于教程,认识到这种方法将限制我的两个端点:


var limiter = rate.NewLimiter(rate.Every((1*time.Hour)/3), 1)


func limit(next http.Handler) http.Handler {

    return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {

        if limiter.Allow() == false {

            http.Error(res, http.StatusText(429), http.StatusTooManyRequests)

            return

        }

        next.ServeHTTP(res, req)

    })

}


func main() {

    mux := http.NewServeMux()

    mux.HandleFunc("/", createNewToken)

    mux.HandleFunc("/notify", sendPushNotificationToAllTokens)


    log.Fatal(http.ListenAndServeTLS(":5050", "localhost.crt", "localhost.key", limit(mux)))

}

我研究了http.Handle 和 http.HandleFunc之间的区别,天真地认为我可以http.HandleFunc 替代http.Handle. 这种方法是完全有缺陷的,因为永远不会执行中包含的逻辑HandlerFunc:


var limiter = rate.NewLimiter(rate.Every(1*time.Hour/3), 1)


func limit(next http.HandlerFunc) http.HandlerFunc {

    return func(res http.ResponseWriter, req *http.Request) {

        if limiter.Allow() == false {

            http.Error(res, http.StatusText(429), http.StatusTooManyRequests)

            return

        }

        next.ServeHTTP(res, req)

    }

}


func main() {

    //mux := http.NewServeMux()

    http.HandleFunc("/", createNewToken)

    http.HandleFunc("/notify", sendPushNotificationToAllTokens)


    // attempt to only rate limit the /notify endpoint 

    log.Fatal(http.ListenAndServeTLS(":5050", "localhost.crt", "localhost.key", limit(sendPushNotificationToAllTokens)))

谁能解释为什么这不起作用,以及我如何解决这个问题以仅对特定端点进行速率限制?


FFIVE
浏览 71回答 1
1回答

温温酱

使用 plainhttp.Handler和 a之间的区别http.HanlderFunc在这里并不重要。http.HandleFunc只是一种将常规函数转换为 a 的方法http.Handler- 它本质上与原始版本的limit.您对limit两者的实现看起来都不错;可能第二个更好,因为它更简单。相反,问题出在main. 当您调用http.ListenAndServeTLS并为最终参数提供值时,它会请求仅将您作为最终参数传入的处理程序用作根请求处理程序。除非您作为最后一个参数传入,否则对http.Handle()或的任何调用都会被忽略。http.HandleFunc()nil您要做的是应用于limit您要限制的特定处理程序。为此,您有两种选择。ServeMux首先,您可以在第一个代码片段中使用like:func main() {    mux := http.NewServeMux()    mux.HandleFunc("/", createNewToken)    // Limit only the handler for "/notify".    mux.HandleFunc("/notify", limit(sendPushNotificationToAllTokens))    // Don't limit the whole mux.    log.Fatal(http.ListenAndServeTLS(":5050", "localhost.crt", "localhost.key", mux))}nil或者,您可以做一些更像您的第二个代码片段的事情,但将最后一个参数传递给http.ListenAndServeTLS以便http.ServeMux使用默认值,这意味着http.HandleFunc()将尊重对的调用:func main() {    http.HandleFunc("/", createNewToken)    // Limit only the handler for "/notify".    http.HandleFunc("/notify", limit(sendPushNotificationToAllTokens))    // Pass in nil here so that http.DefaultServeMux is used.    log.Fatal(http.ListenAndServeTLS(":5050", "localhost.crt", "localhost.key", nil))}对于一个简单的应用程序,第一种方法可能没问题。对于更复杂的事情,我推荐后一种方法,因为如果您打开多个服务器或做其他更复杂的事情,它就会起作用。
随时随地看视频慕课网APP

相关分类

Go
我要回答