0
0

【Go】クッキー

Last updated at Posted at 2024-07-10

はじめに

前回、レスポンスについてまとめたのですが、長くなるためクッキーは割愛しました。
そこで今回はサーバーからHTTPレスポンスメッセージを通して送られるクッキーについてまとめます。

クッキー

クッキーは、サーバーがクライアントに送信し、クライアント側で保存される情報の小さな断片です。例えば、ブラウザ(Chrome)で検証すれば簡単に確認できます。(下の画像は何も入っていません。)
スクリーンショット 2024-07-10 11.32.43.png

サーバーはステートレスであるため、一度クライアントとのやり取りが終わるとその状態を保持しません。そのため、次のリクエストが来たときにそのクライアントが誰なのかを覚えていません。

例えば、ログインしたユーザーが誰であるかを認識するためには、セッション情報をクッキーに保存し、そのクッキーをリクエストのたびに送信することで、サーバーがユーザーを認識することができます。

余談ですが、最近はプライバシー保護の観点からサードパーティクッキー廃止の流れとなっています。最近よくクッキーを許可するかどうか確認されますよね。(個人的に面倒なのでやめてほしい。)

これに関して、疑問なのですが、フロントとバックエンドでAPI通信する場合、ドメインが異なる時はクッキーを使えなくなるんでしょうか。分かる方誰か教えてください。

Goに話を移します

ちょっと前置きが長くなりましたが、cookieの扱いをGo言語で確認します。

以下がCookie構造体です。まあ、一般的なcookieの設定項目がありますね。

type Cookie struct {
	Name  string
	Value string

	Path       string    // optional
	Domain     string    // optional
	Expires    time.Time // optional
	RawExpires string    // for reading cookies only

	// MaxAge=0 means no 'Max-Age' attribute specified.
	// MaxAge<0 means delete cookie now, equivalently 'Max-Age: 0'
	// MaxAge>0 means Max-Age attribute present and given in seconds
	MaxAge   int
	Secure   bool
	HttpOnly bool
	SameSite SameSite
	Raw      string
	Unparsed []string // Raw text of unparsed attribute-value pairs
}

一点補足すると、MaxAgeExpiersは秒数か日時かの違いなどありますが、期限を決めるという意味では同じものです。ですので、どちらも設定することが可能ですが基本的にMaxAgeが優先されます。

Cookie構造体を使用してクッキーをブラウザに登録してみる

ブラウザにクッキーを登録するためには、HTTPレスポンスヘッダーにSet-Cookieヘッダーを含めます。ブラウザはこのヘッダーを受け取ると、指定されたクッキーを保存します。

したがって、以下のようにCookie構造体に必要な値を設定し、Set-Cookieをキーc.String()を値として、ヘッダーに追加します。

こうすると、レスポンスが返ってくるとブラウザのクッキーにセットされます。

Cookie構造体にはString()がありますが、これは__Cookie構造体をHTTPヘッダー用の文字列に変換し、それを返却してくれます。__

package main

import "net/http"

func CookieSample(w http.ResponseWriter, r *http.Request){
	c := http.Cookie{
		Name: "name",
		Value: "value",
		HttpOnly: true,
	}

	w.Header().Set("Set-Cookie", c.String())
}

func main(){
	server := http.Server{
		Addr: "127.0.0.1:8080",
	}

	http.HandleFunc("/cookie", CookieSample)

	server.ListenAndServe()
}

試しにhttp://127.0.0.1:8080/cookieへブラウザでリクエストすると、以下のようにセットされます。
スクリーンショット 2024-07-10 11.59.50.png

実はSetCookieメソッドがある

ヘッダーにSet-Cookieでクッキーをセットするのでも十分簡単なのですが、実はhttp.SetCookieを使えばより簡潔に書けるみたいです。

先ほどのコードを以下のように変えるだけです。こちらの方が明示的で分かりやすいですね。参照渡しに変わっている点だけ注意が必要です。

	http.SetCookie(w, &c)
	// w.Header().Set("Set-Cookie", c.String())

SetCookieの定義は以下の通りですが、やっていることは同じですね。

func SetCookie(w ResponseWriter, cookie *Cookie) {
	if v := cookie.String(); v != "" {
		w.Header().Add("Set-Cookie", v)
	}
}

クッキーの取得

では、セットしたクッキーを次はサーバー側でどのように取得するのでしょうか。
あまり複雑ではないので簡潔に書きます。

まず、最初に思いつきそうなのが以下のようにHeaderからキーを指定して取得する方法ですが、これだと文字列のスライスが返ってくるため、自分で解析して必要な名前と値のペアを取得する必要があります。

func GetCookie(w http.ResponseWriter, r *http.Request){
    c := r.Header["cookie"]
}

ですので、これを避けるためにCookieメソッドを使用できます。これは引数でクッキーの名前を指定すると、ヘッダーの中からその名前に一致する値を探して、返却します。

func GetCookie(w http.ResponseWriter, r *http.Request){
    c, err := r.Cookie("first_cookie")
}

ちなみにCookie()だと単一のクッキーですが、複数のクッキーを取得したい場合にはCookies()が用意されています。

0
0
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
0
0