2016-04-08 21 views
2

ich eine kleine Website schreibe und für jede Seite, ich einen Servernamen zu seinem Header bin setzen:In jedem Handler-Response-Header ohne die gleiche Linie wiederholen

func httpSignUp(rw http.ResponseWriter, req *http.Request) { 
    rw.Header().Set("Server", SERVER_NAME) 
} 

Ich frage mich, ob es einen Weg gibt ist, dass Ich kann den Standardservernamen von http.ResponseWriter festlegen, damit ich nicht immer dieselbe Zeile verwenden muss?

Antwort

8

einen Wrapper Erstellen die Kopfzeile zu setzen:

func wrap(h http.Handler) http.Handler { 
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (
     r.Header().Set("Server", SERVER_NAME) 
     h.ServeHTTP(w, r) 
    }) 
} 

Wrap Einzellader

http.Handle("/path", wrap(aHandler)(
http.Handle("/another/path", wrap(anotherHandler)) 

oder das Root-Handler ListenAndServe geben:

log.Fatal(http.ListenAndServe(addr, wrap(rootHandler)) 
+1

Weiterführende Literatur: https://justinas.org/writing-http-middleware-in-go/ – elithrar

+0

Vielen Dank – Gon

3

„Bevorzugen Zusammensetzung Vererbung "- Gang of 4

Vererbung wurde in erster Linie nicht in Golang entwickelt. ;)

Wenn Sie ausführliche Erläuterungen zu den warum Teil suchen, ich glaubte, dies auf SO beantwortet wurde, daher möchte ich darauf Sie nur daran: Embedding instead of inheritance in Go.

Nun, können Sie tatsächlich das gleiche Ergebnis mit Muster Adapter Entwurf erzielen, die Sie Funktionalität von einer eingebauten Bibliothek erweitern ermöglicht, und mir seinen Weg flexibler als Vererbung.

func adapter(h http.Handler) http.Handler { 
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 
     r.Header().Set("Server", SERVER_NAME) 
    h.ServeHTTP(w, r) 
    }) 
} 

oder Pass in serverName als Parameter:

func adapter(h http.Handler, serverName string) http.Handler { 
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 
    r.Header().Set("Server", serverName) 
    h.ServeHTTP(w, r) 
    }) 
} 

Schließlich haben Sie die Flexibilität zu wählen, welche Handler (n) zur 'geerbt':

http.Handle("/path", adapter(your_handler)) 

Oder wenn es für jeden Handler gemeint ist, erben Sie einfach den root-Handler:

http.ListenAndServe(port, adapter(root_Handler)) 
+0

Vielen Dank – Gon

3

Die http.ResponseWriter ist eine interface, keine struct. Also, Sie können es nicht direkt erweitern. Sie müssen das interne struct erweitern. Aber es ist kein idiomatischer Weg, um dieses Problem zu lösen.

Ein Ansatz, den Sie verwenden können, ist die Verwendung middleware. middleware ist nur ein Stück Code, der vor Ihrem Hauptanforderungshandler ausgeführt wird und mit dem einige allgemeine Aufgaben ausgeführt werden können.

Zum Beispiel die gleiche Sache mit middleware Ansatz schreiben:

func injectServerHeader(handler http.Handler, serverName string) http.Handler { 
    ourFunc := func(w http.ResponseWriter, r *http.Request) { 
     w.Header().Set("Server", serverName) 
     handler.ServeHTTP(w, r) 
    } 
    return http.HandlerFunc(ourFunc) 
} 

Auf diese Weise können Sie die aktuell http-Handler mit Middleware-wickeln. Sie müssen also nicht immer wieder denselben Code schreiben.

Zum Beispiel:

http.Handle("/some-path", injectServerHeader(aHandler)) 
+0

Vielen Dank – Gon

Verwandte Themen