2014年7月26日土曜日

Golang Cafe #39を開催しました。

Golang Cafe #39を開催しました。

今回も前回に引き続き、Gorilla Toolkitのパッケージを使ってみる会になりました。

使ったのは、gorilla/contextgorilla/sessionsの2つですが、どちらも単純な機能を提供しています。

gorilla/contextの方は、任意の値をcontextに保存しておくだけです。非常に機能が少ないのでサンプルコードの提示も難しいのですが、以下のように使うことができます。

package main

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

 "github.com/gorilla/mux"
 "github.com/gorilla/context"

)

func main() {
 r := mux.NewRouter()


 r.HandleFunc("/", IndexHandler)

 log.Fatal(http.ListenAndServe(":8080", r))

}

func IndexHandler(w http.ResponseWriter, r *http.Request) {
 for _, param := range strings.Split(r.URL.RawQuery, "&") {
  params := strings.Split(param, "=")
  context.Set(r, params[0], params[1])
 }

 fmt.Fprintf(w, "IndexHandler\n")
 fmt.Fprintf(w, "hoge = %s\n", context.Get(r, "hoge"))
 fmt.Fprintf(w, "fuga = %s\n", context.Get(r, "fuga"))
}

context.Set(http.Request, キー、値);でリクエストが生きている間はキーと値のペアによって保存されます。非常に単純ですが、パラメータを解析した後、contextの中に保存するなどすれば、便利に使えるのか?と考えていましたが、どうやら、gorillaの他のパッケージの内部で使われているようです。単体で使ったりすることがあるかどうかは、当日の話では出なかったと思います。

次に、gorilla/sessionsを使ってみました。
sessionsを使うポイントは、パッケージ変数にsessions.NewCookieStore()で新しく確保する変数を定義しておきます。
この定義した変数内にsessionの値が保存されることになります。

package main

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

 "github.com/gorilla/mux"
 "github.com/gorilla/sessions"

)

func main() {
 r := mux.NewRouter()


 r.HandleFunc("/", IndexHandler)
 r.HandleFunc("/session", SessionHandler)

 log.Fatal(http.ListenAndServe(":8080", r))

}

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

func IndexHandler(w http.ResponseWriter, r *http.Request) {
 session, _ := store.Get(r, "mysession")

 session.Values["hoge"] = "1"
 session.Values[2] = 2

 session.Save(r, w)

 fmt.Fprintf(w, "IndexHandler\n")
}

func SessionHandler(w http.ResponseWriter, r *http.Request) {
 session, _ := store.Get(r, "mysession")

 fmt.Println(session)

 hoge := session.Values["hoge"]
 val := session.Values[2]

 session.Values["hoge"] = "session"
 session.Values[2] = 5

 session.Save(r, w)

 fmt.Fprintf(w, "SessionHandler [%s] [%d]\n", hoge, val)

}

動きとしては、sessionの動きと同じだったのですが、
なぜか、

  • サーバを再起動してもsessionが残っている
  • Chromeを閉じてもSessionの値が残っている

という現象に遭遇して、原因を特定する作業に没頭しました。
シークレット・ウインドウを使った場合は、ブラウザを閉じるとsessionは無くなっていました。(Windowsの場合は、シークレット・ウインドウを閉じても残っているということでしたが、環境なのか、設定なのかは特定できていません)

実際、ChromeのDevToolでCookieの中身を確認すると、session IDだけが保存されているかと思っていたら、データがかなり多く、どうやら、Cookieの中に全てのデータが保存されているようです。確かに、GAEなどのように複数のインスタンスが起動するような時に、サーバ側のメモリにのみ保存しておくと、別のインスタンスにリクエストが送られてしまった時に困るのでこういう実装になっているのだろうと考えていました。

が、Cookieのデータは4KBまでという制約があるので、Sessionに何でもかんでも入れておけば良いという考えはやめておきましょう。

次回も、Gorilla Toolkitの残りのパッケージ(reverse、rpc、schema、securecookie)を読み進めます。