Go言語

【Go言語】net/http ハンドラー関数をラップする

no image
【Go言語】net/httpパッケージの基本的なことまとめ(シンプルなHTTPサーバー実装)

Go言語を学び始めたときnet/httpを使って簡単なものを作ったりしていましたが、echoを使ったプロジェクトに参画してから触れることなく過ごしてきました。 しかしGoでオススメのWebフレームワー ...

続きを見る

↑の記事で net/http パッケージを使ったHTTPサーバーの実装についてまとめましたが、今回はハンドラー関数をラップする方法をメモメモ。

アプリケーションを実装していると、ServeHTTP メソッドが呼ばれる前後に処理をはさみたいことがあります。

例えば、ログインが必要なハンドラーの場合は未ログインならログイン画面にリダイレクトさせるとか。

このようなときはハンドラー関数をラップすればOK。

サンプルコード

すべてmain.goに書く想定です。

例として、ログインしていなければログインページにリダイレクトさせるAuthHandlerを作ります。


package main

import (
	"fmt"
	"log"
	"net/http"
)

type AuthHandler struct {
	next http.Handler
}

func (h *AuthHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	token, err := r.Cookie("auth_token")
	if err == http.ErrNoCookie {
		// ログイン画面へリダイレクト
		w.Header().Set("Location", "/login")
		w.WriteHeader(http.StatusTemporaryRedirect)
		return
	} else if err != nil {
		panic(err)
	}

	// 本来はcookieの値を検証して
	if len(token.Value) > 0 {
		// ラップされたハンドラを呼ぶ
		h.next.ServeHTTP(w, r)
	}
}

func MustAuth(handler http.Handler) http.Handler {
	return &AuthHandler{next: handler}
}

 

ログインしている必要がある場合は、この MustAuth を使えばOK。例えばマイページにアクセスするためにはログインしている必要があるとか。


type MyPageHandler struct{}

func (h *MyPageHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, "マイページ")
}

func main() {
	http.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintln(w, "ログイン画面")
	})
	http.Handle("/mypage", MustAuth(&MyPageHandler{}))

	if err := http.ListenAndServe(":8080", nil); err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}

 

サンプルコード全体


package main

import (
	"fmt"
	"log"
	"net/http"
)

type AuthHandler struct {
	next http.Handler
}

func (h *AuthHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	token, err := r.Cookie("auth_token")
	if err == http.ErrNoCookie {
		// ログイン画面へリダイレクト
		w.Header().Set("Location", "/login")
		w.WriteHeader(http.StatusTemporaryRedirect)
		return
	} else if err != nil {
		panic(err)
	}

	// 本来はcookieの値を検証して
	if len(token.Value) > 0 {
		// ラップされたハンドラを呼ぶ
		h.next.ServeHTTP(w, r)
	}
}

func MustAuth(handler http.Handler) http.Handler {
	return &AuthHandler{next: handler}
}

type MyPageHandler struct{}

func (h *MyPageHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, "マイページ")
}

func main() {
	http.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintln(w, "ログイン画面")
	})
	http.Handle("/mypage", MustAuth(&MyPageHandler{}))

	if err := http.ListenAndServe(":8080", nil); err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}

サンプルコード動作確認

go run main.go して

http://localhost:8080/mypage にアクセスします。 すると /login にリダイレクトされます。

次にdeveloper tools でcookieに適当な値を入れて

 

http://localhost:8080/mypage にアクセスすると「マイページ」と表示されます。

 

参考図書

Tour of Goを終えた人にオススメです!!

-Go言語

© 2021 フリエン生活 Powered by AFFINGER5