gorilla/websocket で異なるOrgin間の Error during WebSocket handshake: Unexpected response code: 403 を回避する

はじめに

go の websocket サーバー gorilla/websocket に対して Angular の rxjs/webSocket を利用して簡単なチャットアプリを作成していたところ Error during WebSocket handshake: Unexpected response code: 403 なるエラーに遭遇しました。

結論としては websocket の upgrade の originチェックに引っかかっていたようです。その回避策をまとめます。

gorilla/websocket の CORS

websocket の handshake が失敗してそうなエラーで、同一orginにあるフロントエンドでは handshake が成功するので、CORSかな。と考えて以下のように書くわけです。

func serveWs(hub *Hub, w http.ResponseWriter, r *http.Request) {

    // Add CORS header...
    w.Header().Set( "Access-Control-Allow-Origin", r.RemoteAddr )
    w.Header().Set( "Access-Control-Allow-Credentials", "true" )
    w.Header().Set( "Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization" )
    w.Header().Set( "Access-Control-Allow-Methods","GET, POST, PUT, DELETE, OPTIONS" )

    conn, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        return
    }
    client := &Client{hub: hub, conn: conn, send: make(chan []byte, 256)}
    client.hub.register <- client

    go client.writePump()
    go client.readPump()
}

が、ダメ。

WebSocket connection to 'ws://localhost:8080/ws/' failed: Error during WebSocket handshake: Unexpected response code: 403

websocket のhandshake 内のシーケンスで origin をチェックしているようで、以下のように雑にチェックしてあげることで接続できるようになりました。

var upgrader = websocket.Upgrader{
    ReadBufferSize:  1024,
    WriteBufferSize: 1024,
    // Add this lines
    CheckOrigin: func(r *http.Request) bool {
        return true
    },
}

まとめ

gorilla/websocket の CORS エラーに対応してみました。
websocket 自体に認証の仕組みがないので、upgradeする前に orgin の検証やユーザー認証をしなさい。という感じのようです。