Last active
January 14, 2021 12:57
-
-
Save jsidew/573d3808306fdb6b6b4e269e4b2852ef to your computer and use it in GitHub Desktop.
Fluent Middleware in Go ~ https://jacoposalvestrini.medium.com/fluent-middleware-in-golang-7ee7f20427fd
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This is a code snippet related to Jacopo Salvestrini's medium.com article | |
// https://medium.com/@jacoposalvestrini/fluent-middleware-in-golang-7ee7f20427fd | |
// * * * | |
// A Fluent evolution (check-out the diffs between commits) | |
// of the adapter pattern from Mat Ryer's article | |
// https://medium.com/@matryer/writing-middleware-in-golang-and-how-go-makes-it-so-much-fun-4375c1246e81 | |
package main | |
import "net/http" | |
func Adapt(h http.Handler) *AdaptedHandler { | |
return &AdaptedHandler{h} | |
} | |
func AdaptFunc(f func(http.ResponseWriter, *http.Request)) *AdaptedHandler { | |
return &AdaptedHandler{http.HandlerFunc(f)} | |
} | |
type AdaptedHandler struct { | |
handler http.Handler | |
} | |
func (a *AdaptedHandler) With(adapters ...Adapter) http.Handler { | |
h := a.handler | |
last := len(adapters) - 1 | |
for i := range adapters { | |
h = adapters[last-i](h) | |
} | |
return h | |
} | |
type Adapter func(http.Handler) http.Handler |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"net/http" | |
) | |
type Index struct{} | |
func (Index) ServeHTTP(w http.ResponseWriter, r *http.Request) { | |
fmt.Fprint(w, "Hello World from a ServeHTTP ") | |
fmt.Fprintln(w, r.URL.Path) | |
} | |
func IndexHandlerFunc(w http.ResponseWriter, r *http.Request) { | |
fmt.Fprint(w, "Hello World from a func ") | |
fmt.Fprintln(w, r.URL.Path) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This is a code snippet related to Jacopo Salvestrini's medium.com article | |
// https://medium.com/@jacoposalvestrini/fluent-middleware-in-golang-7ee7f20427fd | |
// * * * | |
// A Fluent evolution (check-out the diffs between commits) | |
// of the adapter pattern from Mat Ryer's article | |
// https://medium.com/@matryer/writing-middleware-in-golang-and-how-go-makes-it-so-much-fun-4375c1246e81 | |
package main | |
import ( | |
"fmt" | |
"io" | |
"net/http" | |
"github.com/gorilla/handlers" | |
) | |
type Logger interface { | |
Some(string) | |
GetWriter() io.Writer | |
} | |
type DataProvider interface { | |
Connect() | |
Close() | |
} | |
type AuthProvider interface { | |
Check(*http.Request) bool | |
} | |
func Notify(log Logger) Adapter { | |
return func(h http.Handler) http.Handler { | |
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
defer log.Some("Call end " + r.URL.Path) | |
log.Some("Call start " + r.URL.Path) | |
handlers.CombinedLoggingHandler(log.GetWriter(), h).ServeHTTP(w, r) | |
}) | |
} | |
} | |
func CopyMgoSession(dp DataProvider) Adapter { | |
return func(h http.Handler) http.Handler { | |
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
defer dp.Close() | |
dp.Connect() | |
h.ServeHTTP(w, r) | |
}) | |
} | |
} | |
func CheckAuth(provider AuthProvider) Adapter { | |
return func(h http.Handler) http.Handler { | |
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
if !provider.Check(r) { | |
w.WriteHeader(http.StatusUnauthorized) | |
fmt.Fprintln(w, "Get out of here!") | |
return | |
} | |
h.ServeHTTP(w, r) | |
}) | |
} | |
} | |
func AddHeader(name, value string) Adapter { | |
return func(h http.Handler) http.Handler { | |
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
w.Header().Set(name, value) | |
h.ServeHTTP(w, r) | |
}) | |
} | |
} | |
func Compress(level int) Adapter { | |
return func(h http.Handler) http.Handler { | |
return handlers.CompressHandlerLevel(h, level) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"io" | |
"net/http" | |
) | |
type Log struct { | |
out io.Writer | |
} | |
func (l Log) Some(thing string) { | |
fmt.Fprintln(l.out, thing) | |
} | |
func (l Log) GetWriter() io.Writer { | |
return l.out | |
} | |
type DB struct{} | |
func (d DB) Connect() { | |
fmt.Println("connection to MongoDB established") | |
} | |
func (d DB) Close() { | |
fmt.Println("connection to MongoDB closed") | |
} | |
type Auth struct{} | |
func (p Auth) Check(r *http.Request) bool { | |
fmt.Printf("checking request header %v\n", r.Header) | |
return true | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This is a code snippet related to Jacopo Salvestrini's medium.com article | |
// https://medium.com/@jacoposalvestrini/fluent-middleware-in-golang-7ee7f20427fd | |
// * * * | |
// A Fluent evolution (check-out the diffs between commits) | |
// of the adapter pattern from Mat Ryer's article | |
// https://medium.com/@matryer/writing-middleware-in-golang-and-how-go-makes-it-so-much-fun-4375c1246e81 | |
package main | |
import ( | |
"net/http" | |
"os" | |
"github.com/gorilla/mux" | |
) | |
func main() { | |
var ( | |
logger = Log{os.Stdout} | |
db = DB{} | |
provider = Auth{} | |
indexHandler = Index{} | |
) | |
r := mux.NewRouter() | |
r.Handle("/hello", Adapt(indexHandler).With( | |
CopyMgoSession(db), | |
CheckAuth(provider), | |
)) | |
// No Auth check for this endpoint | |
r.Handle("/hellofunc", AdaptFunc(IndexHandlerFunc).With( | |
CopyMgoSession(db), | |
)) | |
if err := http.ListenAndServe(":8080", Adapt(r).With( | |
Notify(logger), | |
Compress(5), | |
AddHeader("Server", "Mine"), | |
)); err != nil { | |
panic(err) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment