Golangで簡易版ミドルウェア

2015-08-26

サーバプログラムでログイン処理など共通の処理を行うのにミドルウェアを使用することは多いと思いますが、Golangではこんな簡単なコードで実現できます。

Golangでミドルウェアの必要性を感じたとき、みなさんはどうしていますか?

おそらく、Githubあたりで公開されているミドルウェアを導入したり、フレームワークに頼ったりするのが一般的ではないでしょうか?

しかし、そこまで仰々しいものではなくて、単に共通の処理をくくりだしたいというだけなら、こんな簡単なコードで実現できます。

簡易版ミドルウェア

package app

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

func Handle(handlers ...func(w http.ResponseWriter, r *http.Request) error) func(w http.ResponseWriter, r *http.Request) {
    return func(w http.ResponseWriter, r *http.Request) {
        for _, handler := range handlers {
            if err := handler(w, r); err != nil {
                c := appengine.NewContext(r)
                c.Errorf("Error %v", err)
                return
            }
        }
    }
}

func init() {
    http.HandleFunc("/", Handle(loginHandler, mainHandler))
}

func mainHandler(w http.ResponseWriter, r *http.Request) error {
    fmt.Fprint(w, "ログインした後の処理")
    return nil
}

func loginHandler(w http.ResponseWriter, r *http.Request) error {
    fmt.Fprint(w, "ログイン処理\n")
    return nil
}

これはGoogle App Engineで動かすために書いたコードですが、一般的なサーバでも同様に書けると思います。

Handle関数は、引数に(複数の)関数をとる関数で、それらの関数を順次実行します。途中でエラーを返すと、そこで終了します。

なので、まずログイン処理(loginHandler)を実行して、次にメインの処理を実行するという一連の流れをわかりやすく表現できます。

例によって元ネタがありまして、Writing Handsome Golang Middlewareで、私もハンサムになれたでしょうか?

GolangGoogle App Engine