🌐
GolangでCookie付きのWebsocket通信を行う
意外と情報が無くて苦しんだのでメモ
websocketのライブラリはgorrila/websocketを利用した。
簡単なテストを目的にしたツールのため、実用には耐えないコードであることに注意。
Code
package main
import (
"net/http/cookiejar"
"net/url"
"github.com/gorilla/websocket"
"github.com/pkg/errors"
)
var (
host = "nowhere:4649"
path = "super/websocket/form"
)
func main() {
u := &url.URL{Scheme: "http", Host: host, Path: path}
jar, err := cookiejar.New(nil)
if err != nil {
return nil, errors.WithStack(err)
}
cookies := []*http.Cookie{}
cookie := &http.Cookie{
Name: "TASTE_OF_COOKIE",
Value: "VERY_DELICIOUS",
Path: "/",
Domain: "localhost",
}
cookies = append(cookies, cookie)
jar.SetCookies(u, cookies)
dialer := websocket.Dialer{}
dialer.Jar = jar
con := url.URL{Scheme: "ws", Host: host, Path: path}
c, _, err := dialer.Dial(con.String(), nil)
return c, nil
# websocket send
err := c.WriteMessage(websocket.TextMessage, []byte("Hello world"))
if err != nil {
log.Println("write:", err)
return
}
# websocket receive
_, message, err := c.ReadMessage()
if err != nil {
log.Println("read:", err)
return
}
log.Printf("received: %s", message)
}
解説
Cookieの作成とセット
gorilla/websocketでは、dialer.Dial()を呼び出すことでwebsocket通信を確立させることができるが、この時dialer.JarにCookieを持たせることで、通信開始時にCookieを送信することができる。
type Dialer struct {
// 上略
// Jar specifies the cookie jar.
// If Jar is nil, cookies are not sent in requests and ignored
// in responses.
Jar http.CookieJar
}
http.CookieJarはただのinterfaceなので、その実装であるnet/http/cookiejarを利用した。
cookiejar.Jarでは、SetCookies()することでCookieをJarにセットすることができる。
この時、第一引数に指定する*url.URLのschemeがhttp,https以外の場合、サイレントにCookieが捨てられることに注意。
SetCookies implements the SetCookies method of the http.CookieJar interface.
It does nothing if the URL's scheme is not HTTP or HTTPS.
Websocket通信
後はいつも通りWriteMessage()、ReadMessage()して通信を行うことができる。
感想
Cookieのことをよく分かってないマンだったので、解決の糸口をどこから探るべきなのか苦労した...
GoDocをよく読んだりライブラリのコードを眺めることで解決できたので、そういう地道な作業が大事だと思いました(KONAMI)
Discussion