🌐
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