Go言語で、MiddleWareを作成します。
事前準備
任意の場所にフォルダとファイルを作成しましょう。
1 2 3 |
mkdir middleware touch middleware/main.go cd middleware |
Get User Middleware
ユーザーの情報を取得する簡単なMiddlewareを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
package main import ( "encoding/json" "fmt" "net/http" ) type person struct { Name string Age uint64 } func postHandler(w http.ResponseWriter, r *http.Request) { if r.Method == "POST" { var personInfo person decoder := json.NewDecoder(r.Body) err := decoder.Decode(&personInfo) if err != nil { panic(err) } defer r.Body.Close() fmt.Printf("Got %s's name with %d years old!\n", personInfo.Name, personInfo.Age) w.WriteHeader(http.StatusOK) w.Write([]byte("201 - Created")) } else { w.WriteHeader(http.StatusMethodNotAllowed) w.Write([]byte("405 - Method Not Allowed")) } } func main() { http.HandleFunc("/person", postHandler) fmt.Println("Start Server...") http.ListenAndServe(":8000", nil) } |
terminalを2つ立ち上げて、それぞれコマンドを入力しましょう。
1 2 3 4 5 6 7 8 9 10 11 |
# terminal1 go run main.go # terminal2 curl -H "Content-Type: application/json" -X POST # terminal1 Got Selfnote's name with 31 years old! # terminal2 201 - Createdh |
Content-TypeとSetCookie MiddleWare
Content-TypeとCookieの値をチェックするMiddlewareを追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
package main import ( "encoding/json" "fmt" "log" "net/http" "strconv" "time" ) type person struct { Name string Age uint64 } func postHandler(w http.ResponseWriter, r *http.Request) { if r.Method == "POST" { var personInfo person decoder := json.NewDecoder(r.Body) err := decoder.Decode(&personInfo) if err != nil { panic(err) } defer r.Body.Close() fmt.Printf("Got %s's name with %d years old!\n", personInfo.Name, personInfo.Age) w.WriteHeader(http.StatusOK) w.Write([]byte("201 - Created")) } else { w.WriteHeader(http.StatusMethodNotAllowed) w.Write([]byte("405 - Method Not Allowed")) } } // new func filterContentType(handler http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { log.Println("Currently in the check content type middleware") // Filtering requests by MIME type if r.Header.Get("Content-type") != "application/json" { w.Write([]byte("415 - Unsupported Media Type. Please send JSON")) return } handler.ServeHTTP(w, r) }) } // new func setServerTimeCookie(handler http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { handler.ServeHTTP(w, r) // Setting cookie to every API response cookie := http.Cookie{Name: "Server-Time(UTC)", Value: strconv.FormatInt(time.Now().Unix(), 10)} http.SetCookie(w, &cookie) log.Println("Currently in the set server time middleware") }) } func main() { originalHandler := http.HandlerFunc(postHandler) http.Handle("/person", filterContentType(setServerTimeCookie(originalHandler))) fmt.Println("Start Server...") http.ListenAndServe(":8000", nil) } |
terminalを2つ立ち上げて、それぞれコマンドを入力しましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# terminal1 go run main.go # terminal2 curl -i -H "Content-Type: application/json" -X POST http://localhost:8000/person -d '{"name":"Selfnote", "age":31}' # terminal1 Start Server... 2020/03/19 21:00:55 Currently in the check content type middleware Got Selfnote's name with 31 years old! 2020/03/19 21:00:55 Currently in the set server time middleware # terminal2 HTTP/1.1 200 OK Date: Thu, 19 Mar 2020 12:00:55 GMT Content-Length: 13 Content-Type: text/plain; charset=utf-8 |
Aliceパッケージの導入
aliceパッケージを活用するとミドルウェアの連結が多少楽になります。
1 |
go get github.com/justinas/alice |
前回のコードのmain関数を修正します。
1 2 3 4 5 6 7 8 |
func main() { originalHandler := http.HandlerFunc(postHandler) chain := alice.New(filterContentType, setServerTimeCookie).Then(originalHandler) http.Handle("/person", chain) fmt.Println("Start Server...") http.ListenAndServe(":8000", nil) } |
だいぶスッキリしましたね。
Gorilla Handler
gorilla/handlersパッケージも便利です。
一例として、loggingミドルウェアを使ってみましょう。
1 |
go get "github.com/gorilla/handlers" |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
package main import ( "log" "net/http" "os" "github.com/gorilla/handlers" "github.com/gorilla/mux" ) func handle(w http.ResponseWriter, r *http.Request) { log.Println("Start Process") w.Write([]byte("OK")) log.Println("End Process") } func main() { r := mux.NewRouter() r.HandleFunc("/", handle) loggedRouter := handlers.LoggingHandler(os.Stdout, r) http.ListenAndServe(":8000", loggedRouter) } |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# terminal 1 go run main.go # terminal 2 curl -X GET localhost:8000 # terminal 1 2020/03/21 06:53:41 Start Process 2020/03/21 06:53:41 End Process ::1 - - [21/Mar/2020:06:53:41 +0900] "GET / HTTP/1.1" 200 2 # terminal 2 OK |
まとめ
MiddleWareを導入すると、処理の間に実行したい中間処理みたいなものが入れられるので、大変便利ですね!
サンプルでは、正常系のCurlのみ実行してみましたが、異常系のCurlも実行してみてください(誤ったContent-Typeを指定するなど)!
コメントを残す
コメントを投稿するにはログインしてください。