2017-09-19 3 views
0

Ich entwickle eine Go-Webanwendung, die verschiedene Middlewarefunktionen beim Routing unterstützt. Ich versuche, so weit wie möglich zu net/http zu bleiben und fragte mich, wie ich dies ohne die Verwendung von Middleware-Bibliotheken wie negroni erreichen könnte.Nest-Funktionen von Slice

Im Wesentlichen möchte ich in der Lage sein, ein Stück Middlewarefunktionen zu liefern, zum Beispiel eine für die Protokollierung, eine für die Suche nach einer gültigen JWT und schließlich den Handler für die Bearbeitung der Anfrage.

ich in der Lage bin das ziemlich einfach mit negroni zu tun, indem Sie die folgenden Struktur zu definieren:

// Route .. 
type Route struct { 
    Method  string 
    Path  string 
    Middleware []negroni.Handler 
    Handler http.HandlerFunc 
} 

und dann definieren, eine Route wie:

var commonRoutes = []Route{ 
    { 
     Method:  "GET", 
     Path:  "/info", 
     Middleware: []negroni.Handler{negroni.HandlerFunc(middleware.CheckCache), negroni.HandlerFunc(middleware.Authenticated), negroni.NewLogger()}, 
     Handler: handlers.APIInfo, 
    }, 
} 

Schließlich, wenn ich meinen Server booten, ich Importieren Sie die Liste der Routen und registrieren Sie sie wie folgt:

for _, r := range routes { 

    handler := append(r.Middleware, negroni.Wrap(r.Handler)) 

    router.Handle(r.Path, negroni.New(handler...)).Methods(r.Method) 
} 

Und das funktioniert perfekt.

Jede Idee, wie ich in der Lage sein könnte, diese zu definieren, Middleware-Handler nur die Standard-net/http Unterschrift und Weise mit dem zu tun, die wie folgt aussehen:

http.Handle("/", middlewareOne(middlewareTwo(finalHandler))) 

Danke :)

Antwort

1
func Auth(n http.Handler) http.Handler { 
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 
     log.Printf("Start") 
     n.ServeHTTP(w, r) 
     log.Printf("End") 
    }) 
} 

func processReq(w http.ResponseWriter, r *http.Request) { 
    w.Write([]byte("Success")) 
} 


func main() { 
    handler := http.HandlerFunc(processReq) 

    http.Handle("/",Auth(handler)) 
    http.ListenAndServe(":8000", nil) 
} 

können gemacht werden mit http.handler

0

Einfach. Sie definieren jeder Handler wie folgt:

// So I don't have to type it over and over... 
type HTTPHandler func(w http.ResponseWriter, r *http.Request) 

func Handler1(next HTTPHandler) HTTPHandler { 
    return func(w http.ResponseWriter, r *http.Request){ 
     // Do stuff 

     if next != nil { 
      next(w, r) 
     } 
    } 
} 

// Handler2 ... HandlerN defined in the same basic way. 

// Chaining: 
http.Handle("/", Handler1(Handler2(nil))) 

Jeder Handler nimmt den nächsten Handler und gibt einen Verschluss, der tut, was Sie wollen und den nächsten Handler aufrufen. Wenn Sie viele davon benötigen, kann es sinnvoll sein, einen ähnlichen Helfer wie diesen zu schreiben:

func MakeHandler(worker, next HTTPHandler) HTTPHandler { 
    return func(w http.ResponseWriter, r *http.Request){ 
     // Maybe have to worker return an error and do standard error 
     // handling here? Could simplify your code some depending on 
     // what you are doing. 
     worker(w, r) 

     if next != nil { 
      next(w, r) 
     } 
    } 
}