ポンコツエンジニアのごじゃっぺ開発日記。

いろいろポンコツだけど、気にするな。プログラム&ロボット大好きなポンコツが日々の記録を残していきます。 自動で収入を得られるサービスやシステムを作ることが目標!!

Go言語フレームワークechoのcookieでつまずいた話。

最近Golangにハマっていて、特にechoというフレームワークを使ってみよう!と思って、echoに手を出してみました。で、ドキュメントの上の方に書いてあり、またwebサービスを作るのであれば必須になるCookieをまず初めに触ってみようと思いまして、今回実際に使ってみました。

 

Cookie

ドキュメントには以下のように書いてあります。

Create a Cookie

func writeCookie(c echo.Context) error {
  cookie := new(http.Cookie)
  cookie.Name = "username"
  cookie.Value = "jon"
  cookie.Expires = time.Now().Add(24 * time.Hour)
  c.SetCookie(cookie)
  return c.String(http.StatusOK, "write a cookie")
}

new(http.Cookie)をして、パラメータ(attributes)を入力(assigning)して、最後にc.SetCookie(cookies)を実行するだけで、HTTPレスポンスヘッダーのSet-Cookieに追加されます。

 

Read a Cookie

func readCookie(c echo.Context) error {
  cookie, err := c.Cookie("username")
  if err != nil {
    return err
  }
  fmt.Println(cookie.Name)
  fmt.Println(cookie.Value)
  return c.String(http.StatusOK, "read a cookie")
}

c.Cookie("username")を呼ぶだけでHTTPリクエストヘッダーから取得することができます。

 

実際にやってみる

という感じに書いてあったので、実際にスクリプトを書いてみました。

route/router.go

package route

import(
  "github.com/labstack/echo"
  "github.com/labstack/echo/middleware"

  "../controller"
)

func Init() *echo.Echo {
  e := echo.New()

  e.Use(middleware.Logger())
  e.Use(middleware.Recover())

  e.GET("/cookie/set/:name", controller.WriteCookie)
  e.GET("/cookie/get", controller.ReadCookie)

  return e
}

controller/cookie.go

package controller

import (
  "net/http"
  "fmt"
  "time"
  "github.com/labstack/echo"
)

func WriteCookie(c echo.Context) error {
  name := c.Param("name")
  cookie := new(http.Cookie)
  cookie.Name = "username"
  cookie.Value = name
  cookie.Expires = time.Now().Add(24 * time.Hour)
  c.SetCookie(cookie)

  return c.String(http.StatusOK, "write a cookie: " + name)
}

func ReadCookie(c echo.Context) error {
  cookie, err := c.Cookie("username")
  if err != nil {
    fmt.Println(err)
    return err
  }
  fmt.Println(cookie.Name)
  fmt.Println(cookie.Value)
  return c.String(http.StatusOK, "read a cookie: " + cookie.Value)
}

上のプログラムを簡単にまとめると

  • /cookie/set/:nameでcookieにnameを入れる
  • /cookie/getでcookieに入っているものを出力する

というもの。

 

これを実際に実行してみました。もちろんブラウザ上でURLを入力して試しています。

 

GET: http://localhost:9999/cookie/set/test

write a cookie: test

GET: http://localhost:9999/cookie/get

{"message":"Internal Server Error"}

あれ?Internal Server Errorになっちゃいました。。

いろいろ調査してみると、

GET: http://localhost:9999/cookie/set/test

これのレスポンスヘッダを見てみると

Set-Cookie: username=test; Expires=Tue, 24 Apr 2018 17:29:47 GMT
GET: http://localhost:9999/cookie/get

これのリクエストヘッダを見てみても受け取ったCookieを渡していません。

もしかして、path属性が/cookie/setになっているのかも!?

あとからみて気づいたのですが、ドキュメントにも書いてあるPathというCookie Attributeを指定してあげることで解決できます。

func WriteCookie(c echo.Context) error {
  name := c.Param("name")
  cookie := new(http.Cookie)
  cookie.Name = "username"
  cookie.Value = name
  cookie.Expires = time.Now().Add(24 * time.Hour)
  cookie.Path = "/"
  c.SetCookie(cookie)

  return c.String(http.StatusOK, "write a cookie: " + name)
}

このようにcookei.Path = "/"を入れてあげます。

すると

GET: http://localhost:9999/cookie/set/test

このレスポンスヘッダは

Set-Cookie: username=test; Path=/; Expires=Tue, 24 Apr 2018 17:40:02 GMT

という感じにPath=/;が追加されました。ということなので、

GET: http://localhost:9999/cookie/get

にアクセスすると

write a cookie: test

と無事ブラウザに出力されるようになりました。

 

まとめ

何が悪かったかというと、Path属性をちゃんと理解してなかったというところ。

Pathをちゃんと指定してあげれば簡単に解決できた問題だったのです。

ということで、これでセッション管理のベース部分をちょっとだけ踏み込めた気がします。やったね!