LoginSignup
3
4

More than 5 years have passed since last update.

golangでRailsのflash的なものを使う

Posted at
def update
  if @user.save
    redirect_to root_path, notice: "success!"
  else
    render :edit, alert: "failed..."
  end
end

このnotice, alertの仕組み(flash)をgolangで書いているwebappでも使いたい。
そして標準パッケージだけで完結させたい。

ということで実装してみた。

flashにメッセージを登録する場所(handler)

こちらは実際のコードを簡易化させています。(ログインのセッション処理など省略)

// handler/register.go

func register(w http.ResponseWriter, r *http.Request) {
    r.ParseForm()
    input := &input.Register{
        Name:     r.FormValue("name"),
        Email:    r.FormValue("email"),
        Password: r.FormValue("password"),
    }

    user, err := usecase.Register(input)

    if err != nil {
        flash.SetAlert(w, e.Error()) // 登録
        http.Redirect(w, r, "/", http.StatusBadRequest)
        return
    }


    flash.SetNotice(w, "success!!") // 登録
    http.Redirect(w, r, "/", http.StatusFound)
}

実際のflash実装

やっていることはシンプルで、

  1. リクエストのたびにcookieからflashの情報を削除
    • これをhandlerのwrapperとして実装するのがポイント
  2. handlerから受け取ったメッセージをcookieにセット

の2つ.

// flash.go

package flash

import "net/http"

// 受け取ったhandlerを処理する前に前回のレスポンスでセットしたflashをクリアするwrapper.
func ClearFlashMessage(h http.HandlerFunc) http.HandlerFunc {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        clearCookie(w, "alert")
        clearCookie(w, "notice")
        h(w, r)
    })
}

func clearCookie(w http.ResponseWriter, name string) {
    c := &http.Cookie{
        Name:     name,
        Value:    "",
        Path:     "/",
        HttpOnly: true,
        MaxAge:   -1, // MaxAge<0 means delete cookie now, equivalently 'Max-Age: 0'
    }
    http.SetCookie(w, c)
}

type Flash struct {
    Alert     string
    HasAlert  bool
    Notice    string
    HasNotice bool
}

func NewFlashFromCookie(r *http.Request) *Flash {
    var alertMsg string
    alert, _ := r.Cookie("alert")
    if alert != nil {
        alertMsg = alert.Value
    }
    var noticeMsg string
    notice, _ := r.Cookie("notice")
    if notice != nil {
        noticeMsg = notice.Value
    }
    return newFlash(alertMsg, noticeMsg)
}

func newFlash(alert, notice string) *Flash {
    return &Flash{
        Alert:     alert,
        HasAlert:  len(alert) > 0,
        Notice:    notice,
        HasNotice: len(notice) > 0,
    }
}

func SetAlert(w http.ResponseWriter, alert string) {
    setFlash(w, alert, "alert")
}

func SetNotice(w http.ResponseWriter, notice string) {
    setFlash(w, notice, "notice")
}

func setFlash(w http.ResponseWriter, msg string, name string) {
    c := &http.Cookie{
        Name:     name,
        Value:    msg,
        Path:     "/",
        HttpOnly: true,
        MaxAge:   100,
    }
    http.SetCookie(w, c)
}
3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4