How do I unregister a Handler in net/http?

前端 未结 3 1442
猫巷女王i
猫巷女王i 2020-12-30 05:35

I am writing a web server wherein I need to register handlers at runtime. E.g. \"/create\" would create a new handler for all URLs like \"/123/*\" and so on. I need a corres

3条回答
  •  感动是毒
    2020-12-30 06:13

    It appears you've already accepted an answer, but I wanted to propose an alternate solution.

    I question the need for adding a custom muxer. In this example I'm using the gorilla muxer, however that's only because I'm familiar with its pattern matching. In theory you could match the pattern from the incoming URL without the need for replacing the default muxer.

    My code maintains the handler functions in a map (string: the handler name => function literal)... This is suitable for using the default muxers HandleFunc method.

    Sample input/output:

    GET /register/123

    GET /123
    hello from123.

    GET /destroy/123

    GET /123
    [nothing]

    package main
    
    import (
        "code.google.com/p/gorilla/mux"
        "flag"
        "log"
        "net/http"
    )
    
    // Wraps server muxer, dynamic map of handlers, and listen port.
    type Server struct {
        Dispatcher *mux.Router
        Urls       map[string]func(w http.ResponseWriter, r *http.Request)
        Port       string
    }
    
    // May the signal never stop.
    func main() {
        //Initialize Server
        server := &Server{Port: "3000", Dispatcher: mux.NewRouter(), Urls: make(map[string]func(w http.ResponseWriter, r *http.Request))}
    
        var port = flag.String("port", "3000", "Default: 3000; Set the port for the web-server to accept incoming requests")
        flag.Parse()
    
        server.Port = *port
        log.Printf("Starting server on port: %s \n", server.Port)
    
        server.InitDispatch()
        log.Printf("Initializing request routes...\n")
    
        server.Start() //Launch server; blocks goroutine.
    }
    
    func (s *Server) Start() {
    
        http.ListenAndServe(":"+s.Port, s.Dispatcher)
    }
    
    // Initialize Dispatcher's routes.
    func (s *Server) InitDispatch() {
        d := s.Dispatcher
    
        // Add handler to server's map.
        d.HandleFunc("/register/{name}", func(w http.ResponseWriter, r *http.Request) {
            //somewhere somehow you create the handler to be used; i'll just make an echohandler
            vars := mux.Vars(r)
            name := vars["name"]
    
            s.AddFunction(w, r, name)
        }).Methods("GET")
    
        d.HandleFunc("/destroy/{name}", func(w http.ResponseWriter, r *http.Request) {
            vars := mux.Vars(r)
            name := vars["name"]
            s.Destroy(name)
        }).Methods("GET")
    
        d.HandleFunc("/{name}", func(w http.ResponseWriter, r *http.Request) {
            //Lookup handler in map and call it, proxying this writer and request
            vars := mux.Vars(r)
            name := vars["name"]
    
            s.ProxyCall(w, r, name)
        }).Methods("GET")
    }
    
    func (s *Server) Destroy(fName string) {
        s.Urls[fName] = nil //remove handler
    }
    
    func (s *Server) ProxyCall(w http.ResponseWriter, r *http.Request, fName string) {
        if s.Urls[fName] != nil {
            s.Urls[fName](w, r) //proxy the call
        }
    }
    
    func (s *Server) AddFunction(w http.ResponseWriter, r *http.Request, fName string) {
        f := func(w http.ResponseWriter, r *http.Request) {
            w.Write([]byte("hello from" + fName))
        }
    
        s.Urls[fName] = f // Add the handler to our map
    }
    

提交回复
热议问题