Golang Cafe #38 まとめ Gorilla web toolkit を試す。 その1

2014/07/13に開催された「Golang Cafe #38」についてのまとめです。

開催からかなり経ってしまいましたが、記録としてまとめておきます。


今回はGorilla is a web toolkitを試してみる会となりました。
Gorilla is a web toolkitとは何か、簡単言うと、Go言語でWeb系のプログラミングを行うのにルーティングやらクッキー(セッション)の処理やらを上手くやってくれるツールキットのようです。フレームワームでは無いようです。


有名所でいうと最近何かと話題のDockerで使われていたり(確認した当時では)、GoogleI/OのGo言語のcodelaboで使用されていたりなど、Go言語ではスタンダードになりつつあるパッケージのようです。


Gorilla is a web toolkitには

  • gorilla/context
  • gorilla/mux
  • gorilla/reverse
  • gorilla/rpc
  • gorilla/schema
  • gorilla/securecookie
  • gorilla/sessions

のパッケージがあるようです。


その中から、今回はgorilla/muxをみてみました。

gorilla/mux

本家の説明はこちらのページ
Go言語でHTTPサーバーを建てる場合には、

http.Handle("/foo", fooHandler)

http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
})

http.ListenAndServe(":8080", nil)

このような感じでルーティングと対応するハンドラを定義します。
あくまでURLとハンドラを結びつけているだけで、GETだろうが、POSTだろうが、パラメータがついていようが、単純にハンドラが呼ばれます。必要であればハンドラ内で処理するというのが比較的一般的なやり方のようです。
これらのような判定処理などやより高度な処理をハンドラが呼ばれれまでにやってしまおうというのがgorilla/muxパッケージです。

まずはインストール。

$ go get github.com/gorilla/mux

ホストやメソッドやヘッダやいろいろな条件でハンドラの呼び出しを制限できるようなのですが、詳細はドキュメントを確認してもらうとして、少しだけサンプルを残しておきます。

func main() {
    r := mux.NewRouter()
    r.HandleFunc("/products/{key}", ProductsHandler)
    r.HandleFunc("/article/{category}", ArticlesCategoryHandler)
    // 正規表現にマッチしない場合は404
    // 最後の/がないと直前のパラメータはなかったことになる
    r.HandleFunc("/article/{category}/{id:[0-9]+}/", ArticleHandler).Methods("GET")

    // 404のときのハンドラ
    r.NotFoundHandler = http.HandlerFunc(NotFoundHandler)

    http.Handle("/", r)

    http.ListenAndServe(":8080", nil)
}

func ProductsHandler(w http.ResponseWriter, r *http.Request) {
    vars := mux.Vars(r)

    for k, v := range vars {
        fmt.Println(k, v)
    }

    w.Write([]byte("ProductsHandler"))
}

func ArticlesCategoryHandler(w http.ResponseWriter, r *http.Request) {
    vars := mux.Vars(r)

    for k, v := range vars {
        fmt.Println(k, v)
    }

    w.Write([]byte("ArticlesCategoryHandler"))
}

func ArticleHandler(w http.ResponseWriter, r *http.Request) {
    vars := mux.Vars(r)

    for k, v := range vars {
        fmt.Println(k, v)
    }

    w.Write([]byte("ArticleHandleer"))
}

func NotFoundHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Println(r)

    http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
}

気をつけておきたいのは、アクセスしたURLがルーティングに定義されていない場合は404になります。また定義するパスの最後に/を必ず付けておかないとダメなようです。
ルーティングが定義されていない場合は、デフォルトのハンドラが定義されているようなのですが、

r := mux.NewRouter()
r.NotFoundHandler = http.HandlerFunc(NotFoundHandler)

のようにすれば独自に404用のハンドラを定義できるようです。

Golang Cafe #39 まとめ Gorilla web toolkit を試す。 その2

2014/07/20に開催された「Golang Cafe #39」についてのまとめです。

開催からかなり経ってしまいましたが、記録としてまとめておきます。


前回に引き続き今回もGorilla is a web toolkitを試してみる会となりました。
その中から、今回はgorilla/contextとgorilla/sessionsをみてみました。

gorilla/context

本家の説明はこちらのページ
何ができるのかというと、リクエストスコープで値を保存しておいたり、取得したりできるものという感じでしょうか。
インストールは

$ go get github.com/gorilla/context

でOKですが、前回muxを試したときに一緒にインストールされたかと思います。


前回gorilla/muxを試してみましたが、
ハンドラ内で解析されたURLのパラメータを取得する際に、

vars := mux.Vars(request)

としたと思いますが、ソースコードを確認すると、内部で、

context.Get(request, キー)

のようなことをしています。
おそらくURLを解析した際にパラメータ(名前/値)をコンテキスト(グローバル変数)に入れておき、ハンドラ内から取得するのに使用しているのだと思います。
リクエストスコープで値を保存しておく場所というような感じで良いと思います。(有効時間は設定できそうです)

gorilla/sessions

本家の説明はこちらのページ
本家の説明を参照すると「クッキーやファイルシステムを使用したセッションや、カスタムセッションのインフラを提供してくれる」らしい。
いわゆるセッションです。
リクエストを跨いで値を保持することができます。その保存先がクッキーやらファイルシステムやらということだと思います。
インストールは他と同じです。

$ go get github.com/gorilla/sessions

本家と同じようなサンプルになりますが載せておきます。

const SESSION_NAME = "session-name"

func main() {
    r := mux.NewRouter()
    r.HandleFunc("/set", MyHandler)
    r.HandleFunc("/get", MyHandler2)

    http.Handle("/", r)

    http.ListenAndServe(":8080", nil)
}

var store = sessions.NewCookieStore([]byte("something-very-secret"))

func MyHandler(w http.ResponseWriter, r *http.Request) {
    session, _ := store.Get(r, SESSION_NAME)
    session.Values["foo"] = "bar"
    session.Values[42] = 43

    session.Save(r, w)

    w.Write([]byte("MyHandler"))
}

func MyHandler2(w http.ResponseWriter, r *http.Request) {
    session, _ := store.Get(r, SESSION_NAME)

    fmt.Println(session.Values["foo"])
    fmt.Println(session.Values[42])

    w.Write([]byte("MyHandler2"))
}

sessions.NewCookieStore でクッキーを使用するセッションストアを定義しておき、store.Getで取り出します。既存のセッションがない場合は作成されます。session.Saveで保存します。
セッションをクリアするには、context.Clear(request)を呼ぶようです。(すいません、未確認です)

基本的なセッションの機能は提供されているので、あとは各々実装すれば良いと思われます。

Golang Cafe #40 まとめ Gorilla web toolkit を試す。 その3

2014/07/27に開催された「Golang Cafe #40」についてのまとめです。

開催からかなり経ってしまいましたが、記録としてまとめておきます。


前回、前々回に引き続き今回もGorilla is a web toolkitを試してみる会となりました。
その中から、今回は残りのgorilla/reverse、gorilla/rpc、gorilla/schema、gorilla/securecookieをかなり駆け足でみていきました。

gorilla/reverse

本家の説明はこちらのページ
インストール。

$ go get github.com/gorilla/reverse

gorilla/muxパッケージはurlを解析してハンドラを呼び出していますが、このパッケージは、正規表現からurlの文字列を生成します。(muxパッケージにもにたような機能がありますが)
簡単なサンプルを載せておきます。

func main() {
    func1()
    func2()
}

func func1() {
    regexp, err := reverse.CompileRegexp(`/foo/1(\d+)3`)

    url, err := regexp.Revert(url.Values{"": {"2"}})

    fmt.Println(url, err)
}

func func2() {
    regexp, err := reverse.CompileRegexp(`/foo/1(?P<two>\d+)3`)
    if err != nil {
        panic(err)
    }
    // url is "/foo/123".
    url, err := regexp.Revert(url.Values{"two": {"2"}})

    fmt.Println(url, err)
}

実行結果は

/foo/123 <nil>
/foo/123 <nil>

1つ目の例は定義した正規表現にパラメータをセットした文字列を返しています。
2つ目の例は名前付きの正規表現を使用しています。

gorilla/rpc

本家の説明はこちらのページ
インストール。

$ go get github.com/gorilla/rpc

Go言語では標準でnet/rpcパッケージがあるのですが、gorilla/rpcは1リクエスト/1呼び出しということらしいです。
この辺りは私がnet/rpcパッケージをまだあまりみていないのではっきりとしたことはよくわかりません。
サーバー側はgorilla/rpcを使用して作成しておきますが、クライアント側はGoの標準的なrpc呼び出しの方法でよさそうです。
サンプルコードは動作が確認できたら掲載しようと思います。

gorilla/schema

本家の説明はこちらのページ
インストール。

$ go get github.com/gorilla/schema

gorilla/schemaパッケージは、マップやポストされたデータから独自に定義した構造体への詰替えを行ってくれるようです。
入れ子のパラメータにも対応しているようなのですが、個人的には配列パラメータの命名方法が気に入りません。

gorilla/securecookie

本家の説明はこちらのページ
インストール。

$ go get github.com/gorilla/securecookie

このパッケージはクッキーなどに入れる値の暗号化、復号化の機能を提供しています。
暗号化に使用するキーはsecurecookie.GenerateRandomKey関数を使用すれば良いとのことです。

まとめ

3回に渡りGorilla web toolkitをみてきましたが、(3回目はかなり駆け足な内容になってしまいましたが)メインとなるのはやはりgorilla/muxパッケージでしょうか。その他にもWebアプリケーションを作成する上で必要となりそうな機能も用意されていているので、簡単なものを作るだけなら十分な気もします。