🔩 ねじき教室 Go と Web の教室

未ログイン時の仕上げ

読了目安 約3分

投稿フォームの出し分けと、未ログインの POST の誘導を実装して、ねじ板を完成させます。

30秒でつかむ ログイン状態で、画面と遷移を分ける
ログイン状態で、画面と遷移を分けるログイン済みなら投稿フォームを表示し、未ログインならログイン画面へ案内します。1ログイン済み投稿できる2セッション確認状態で分ける3未ログインログインへ
  1. ログイン済み 投稿できる
  2. セッション確認 状態で分ける
  3. 未ログイン ログインへ
この章の目次

残っているのは、未ログイン時の振る舞いです。

足すものは次の 2 つです。

  • 投稿フォームをログイン中だけ表示する
  • 未ログインの POST /posts をログイン画面へ誘導する

画面をログイン状態で出し分ける

未ログインの人には投稿フォームの代わりに、ログインと登録への案内を出します。 handleIndex の末尾、ExecuteTemplate を呼んでいた部分を次に置き換えます。

Go
	userName := ""
	userID, loggedIn := currentUserID(r)
	if loggedIn {
		if err := db.QueryRow("SELECT name FROM users WHERE id = ?", userID).Scan(&userName); err != nil {
			serverError(w, err)
			return
		}
	}

	data := map[string]any{
		"Posts":    posts,
		"LoggedIn": loggedIn,
		"UserName": userName,
	}
	if err := templates.ExecuteTemplate(w, "index.html", data); err != nil {
		log.Println(err)
	}

templates/index.html も出し分けに対応させます。 {{if}}{{else}} は、渡した値で出力を切り替えるテンプレートの条件分岐です。

HTML
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>ねじ板</title>
  </head>
  <body>
    <h1>ねじ板</h1>
    {{if .LoggedIn}}
      <p>{{.UserName}} さんとしてログイン中</p>
      <form action="/logout" method="post">
        <button type="submit">ログアウト</button>
      </form>
      <form action="/posts" method="post">
        <textarea name="body" rows="3" cols="40"></textarea>
        <button type="submit">投稿する</button>
      </form>
    {{else}}
      <p>投稿するには<a href="/login">ログイン</a>が必要です。はじめての人は<a href="/register">ユーザー登録</a>へ。</p>
    {{end}}
    <ul>
      {{range .Posts}}
        <li>{{.UserName}}: {{.Body}}({{.CreatedAt.Format "2006-01-02 15:04"}})</li>
      {{end}}
    </ul>
  </body>
</html>

ログアウトがリンクではなく button 付きの form なのは、リンクは GET しか送れないからです(「状態を変える操作は POST」という 1 章の設計)。

未ログインの投稿はログイン画面へ

handleCreatePost の先頭で返していた 401 を、リダイレクトに変えます。

Go
	userID, ok := currentUserID(r)
	if !ok {
		http.Redirect(w, r, "/login", http.StatusSeeOther)
		return
	}
  • POST /posts というリクエスト自体は、画面にフォームが無くても誰でも送れる(前章の curl がそうだった)。画面で隠すのは案内にすぎず、拒む仕事はサーバーにしかできない
  • ここも「続きはこの URL を GET で見よ」という PRG パターンなので、2 章と同じ 303 See Other を使う。302 Found はブラウザによって GET への変更が保証されないため避ける

動作確認

シークレットウィンドウなど未ログインのブラウザで http://localhost:8080 を開いてください。 投稿フォームは無く、ログインへの案内が出ます。 そのままログインすると、フォームとログアウトボタンが現れます。

未ログインの POST も確かめます。

シェル
curl -i -d 'body=未ログインの投稿' http://localhost:8080/posts
テキスト
HTTP/1.1 303 See Other
Location: /login

これでねじ板は完成です。 完成した main.go の全体と、機能を通しで確かめる手順は次章にまとめました。