m_shige1979のときどきITブログ

プログラムの勉強をしながら学習したことや経験したことをぼそぼそと書いていきます

Github(変なおっさんの顔でるので気をつけてね)

https://github.com/mshige1979

golangでgorillaとかいうのを使ってみる(sessions)

セッションを使用してみる

値を入れること自体はそんなに難しく無い感じですけど取り出すときになんかいろいろ手間取る感じ
基本的には構造体などで管理したほうがいい感じです

インストール

go get github.com/gorilla/sessions

実装

main.go
package main

import (
	"encoding/gob"
	"github.com/gorilla/mux"
	"github.com/gorilla/sessions"
	"net/http"
	"fmt"
	"time"
	"html/template"
	"crypto/rand"
	"encoding/base32"
	"io"
	"strings"
)

// セッション名
var session_name string = "gsid"

// Cookie型のstore情報
var store *sessions.CookieStore

// セッションオブジェクト
var session *sessions.Session

// 構造体
type Data1 struct {
	Count    int
	Msg      string
}

// 主処理
func main(){

	// 構造体を登録
	gob.Register(&Data1{})

	// セッション初期処理
	sessionInit()

	// ルーティング生成
	r := mux.NewRouter()

	// URL別の処理
	r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request){

		// セッションオブジェクトを取得
		session, _ := store.Get(r, session_name)

		data1, ok := session.Values["data1"].(*Data1)
		if data1 != nil {
			data1.Count++
			data1.Msg = fmt.Sprintf("%d件カウント", data1.Count)
		} else {
			data1 = &Data1{0, "データ無し"}
		}
		fmt.Println(ok)
		fmt.Println(data1)
		session.Values["data1"] = data1

		// 保存
		sessions.Save(r, w)

		// テンプレートを指定
		tmpl := template.Must(template.New("index").ParseFiles("templates/index.html"))
		tmpl.Execute(w, struct {
			Detail *Data1
		}{
			Detail: data1,
		})

		// logの代わり
		fmt.Print(time.Now())
		fmt.Println(" url = " + r.URL.Path)
	})

	r.HandleFunc("/clear", func(w http.ResponseWriter, r *http.Request){

		// セッション初期化
		sessionInit()

		// logの代わり
		fmt.Print(time.Now())
		fmt.Println(" url = " + r.URL.Path)

		// redirect
		http.Redirect(w, r, "/", http.StatusFound)

	})

	// rを割当
	http.Handle("/", r)

	// ポートを割当
	fmt.Println("localhost:9001")
	http.ListenAndServe(":9001", nil)
}

// セッション用の初期処理
func sessionInit(){

	// 乱数生成
	b := make([]byte, 48)
	_, err := io.ReadFull(rand.Reader, b)
	if err != nil {
		panic(err)
	}
	str := strings.TrimRight(base32.StdEncoding.EncodeToString(b), "=")

	// 新しいstoreとセッションを準備
	store = sessions.NewCookieStore([]byte(str))
	session = sessions.NewSession(store, session_name)

	// セッションの有効範囲を指定
	store.Options = &sessions.Options{
		Domain:     "localhost",
		Path:       "/",
		MaxAge:     0,
		Secure:     false,
		HttpOnly:   true,
	}

	// log
	fmt.Println("key     data --")
	fmt.Println(str)
	fmt.Println("")
	fmt.Println("store   data --")
	fmt.Println(store)
	fmt.Println("")
	fmt.Println("session data --")
	fmt.Println(session)
	fmt.Println("")

}
templates/index.html
{{ define "index" }}
<!DOCType html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>websample2</title>
	</head>
	<body>
		count = {{ .Detail.Count }}<br />
		msg = {{ .Detail.Msg }}<br />
		<br />
		<a href="/clear">クリア<a/>
	</body>
</html>
{{ end }}


セッションのデータ管理は?

store = sessions.NewCookieStore([]byte(str))

これで"store"とかいう変数にCookie形式の形っぽいデータをどっかに管理するみたい
ちなみにローカルファイル内に配置したい場合は

store = sessions.NewFilesystemStore("", []byte(str))

こうなる
第1引数はセッションファイルの配置場所で空文字の場合は規定の場所を指定centosとかでは"/tmp"みたい…

byteで渡す値でデータを管理しているのでデータを初期化するという意味では一度別の名前にするのが良いかと
Valuesの値を消したりしてもいいかもしれないけど面倒な感じもあるので乱数を生成してから消すのも手かと思われる

所感

なんか遅い…
手動でログを出力しているせいかもしれないけどなんか応答が結構遅い感じがする
ルーティングとセッションをとりあえずだけど対応したのでちょっと他のこともやってみる

うーんやることが増えてきたのでソースがでかくなってきた\(^o^)/