Golang的http mux如何更改处理函数?

huangapple go评论85阅读模式
英文:

Golang http mux change handler function

问题

我对Go语言还比较新,没有找到关于这个问题的任何信息,也许目前还不可能实现。

我正在尝试删除或替换mux路由(使用http.NewServeMux或gorilla的mux.Router)。我的最终目标是能够在不重新启动程序的情况下启用/禁用一个路由或一组路由。

我可能可以在处理程序之间实现这一点,如果该功能被“禁用”,只需返回404错误,但我更希望找到一种更通用的方法,因为我想在我的应用程序的每个路由中实现它。

或者,我是否最好跟踪禁用的URL模式,并使用一些中间件来阻止处理程序的执行?

如果有人能至少指点我正确的方向,我绝对会发布代码示例来解决这个问题。谢谢!

英文:

I am fairly new to Go and have not been able to find any information on this, maybe it is just not possible at this time.

I am trying to delete or replace a mux route (using http.NewServeMux, or gorilla's mux.Router). My end goal is to be able to enable/disable a route or set of routes without having to restart the program.

I can probably accomplish this on a handler to handler basis and just return 404 if that feature is "disabled", but I would rather find a more general way to do this since I would like to implement it for every route in my application.

Or would I be better off just keeping track of disabled url patterns and using some middleware to prevent handler execution?

If someone can at least point me in the right direction, I will absolutely post code examples of a solution assuming there is one. Thanks!

答案1

得分: 10

没有内置的方法,但很容易实现。以下是翻译好的代码:

type HasHandleFunc interface { //这样可以适用于gorilla和http.ServerMux
    HandleFunc(pattern string, handler func(w http.ResponseWriter, req *http.Request))
}
type Handler struct {
    http.HandlerFunc
    Enabled bool
}
type Handlers map[string]*Handler

func (h Handlers) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    path := r.URL.Path
    if handler, ok := h[path]; ok && handler.Enabled {
        handler.ServeHTTP(w, r)
    } else {
        http.Error(w, "Not Found", http.StatusNotFound)
    }
}

func (h Handlers) HandleFunc(mux HasHandleFunc, pattern string, handler http.HandlerFunc) {
    h[pattern] = &Handler{handler, true}
    mux.HandleFunc(pattern, h.ServeHTTP)
}

func main() {
    mux := http.NewServeMux()
    handlers := Handlers{}
    handlers.HandleFunc(mux, "/", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("this will show once"))
        handlers["/"].Enabled = false
    })
    http.Handle("/", mux)
    http.ListenAndServe(":9020", nil)
}
英文:

There's no built in way, but it is easy enough to implement play.

type HasHandleFunc interface { //this is just so it would work for gorilla and http.ServerMux
	HandleFunc(pattern string, handler func(w http.ResponseWriter, req *http.Request))
}
type Handler struct {
	http.HandlerFunc
	Enabled bool
}
type Handlers map[string]*Handler

func (h Handlers) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	path := r.URL.Path
	if handler, ok := h[path]; ok && handler.Enabled {
		handler.ServeHTTP(w, r)
	} else {
		http.Error(w, "Not Found", http.StatusNotFound)
	}
}

func (h Handlers) HandleFunc(mux HasHandleFunc, pattern string, handler http.HandlerFunc) {
	h[pattern] = &Handler{handler, true}
	mux.HandleFunc(pattern, h.ServeHTTP)
}

func main() {
	mux := http.NewServeMux()
	handlers := Handlers{}
	handlers.HandleFunc(mux, "/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("this will show once"))
		handlers["/"].Enabled = false
	})
	http.Handle("/", mux)
	http.ListenAndServe(":9020", nil)
}

答案2

得分: 0

是的,你可以这样做。

一种方法是创建一个实现了http.Handle接口并具有ServeHTTP方法的结构体。
然后在结构体中包含另一个muxer,比如gorilla的muxer,
最后使用原子开关来启用/禁用子路由。

这是一个示例代码:

package main

import (
	"fmt"
	"github.com/gorilla/mux"
	"net/http"
	"sync/atomic"
)

var recording int32

func isRecording() bool {
	return atomic.LoadInt32(&recording) != 0
}

func setRecording(shouldRecord bool) {
	if shouldRecord {
		atomic.StoreInt32(&recording, 1)
	} else {
		atomic.StoreInt32(&recording, 0)
	}
}

type SwitchHandler struct {
	mux http.Handler
}

func (s *SwitchHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if isRecording() {
		fmt.Printf("Switch Handler is Recording\n")
		s.mux.ServeHTTP(w, r)
		return
	}

	fmt.Printf("Switch Handler is NOT Recording\n")
	w.WriteHeader(http.StatusNotFound)
	fmt.Fprintf(w, "NOT Recording\n")

}

func main() {
	router := mux.NewRouter()
	router.HandleFunc("/success/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "Recording\n")
	})

	handler := &SwitchHandler{mux: router}

	setRecording(false)

	http.Handle("/", handler)

	http.ListenAndServe(":8080", nil)
}

希望对你有帮助!

英文:

Yes you can.

One way to do it is to have a sturct that implement http.Handle interface with the method
ServeHTTP.
Then have the struct contain another muxer like gorilla's
and finally have an atomic Switch to enable/ disable the subrouting

This is a working example of what I mean:

package main

import (
	"fmt"
	"github.com/gorilla/mux"
	"net/http"
	"sync/atomic"
)

var recording int32

func isRecording() bool {
	return atomic.LoadInt32(&recording) != 0
}

func setRecording(shouldRecord bool) {
	if shouldRecord {
		atomic.StoreInt32(&recording, 1)
	} else {
		atomic.StoreInt32(&recording, 0)
	}
}

type SwitchHandler struct {
	mux http.Handler
}

func (s *SwitchHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if isRecording() {
		fmt.Printf("Switch Handler is Recording\n")
		s.mux.ServeHTTP(w, r)
		return
	}

	fmt.Printf("Switch Handler is NOT Recording\n")
	w.WriteHeader(http.StatusNotFound)
	fmt.Fprintf(w, "NOT Recording\n")

}

func main() {
	router := mux.NewRouter()
	router.HandleFunc("/success/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "Recording\n")
	})

	handler := &SwitchHandler{mux: router}

	setRecording(false)

	http.Handle("/", handler)

	http.ListenAndServe(":8080", nil)
}

答案3

得分: 0

根据https://github.com/gorilla/mux/issues/82的建议,建议交换路由器而不是删除路由。现有的连接将保持打开状态。

英文:

According to https://github.com/gorilla/mux/issues/82 it is suggested to swap the router instead of deleting routes. Existing connections will stay open.

huangapple
  • 本文由 发表于 2014年6月17日 05:27:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/24252500.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定