コンテンツにスキップ

WebSocketクライアント

サーバーとのリアルタイム双方向通信用WebSocketクライアント。

local websocket = require("websocket")
local client, err = websocket.connect("wss://api.example.com/ws")
if err then
return nil, err
end
local client, err = websocket.connect("wss://api.example.com/ws", {
headers = {
["Authorization"] = "Bearer " .. token
},
protocols = {"graphql-ws"},
dial_timeout = "10s",
read_timeout = "30s",
compression = websocket.COMPRESSION.CONTEXT_TAKEOVER
})
パラメータ説明
urlstringWebSocket URL(ws://またはwss://)
optionstable接続オプション(オプション)

戻り値: Client, error

オプション説明
headerstableハンドシェイク用HTTPヘッダー
protocolstableWebSocketサブプロトコル
dial_timeoutnumber/string接続タイムアウト(msまたは”5s”)
read_timeoutnumber/string読み取りタイムアウト
write_timeoutnumber/string書き込みタイムアウト
compressionnumber圧縮モード(定数を参照)
compression_thresholdnumber圧縮する最小サイズ(0-100MB)
read_limitnumber最大メッセージサイズ(0-128MB)
channel_capacitynumber受信チャネルバッファ(1-10000)

タイムアウト形式: 数値はミリ秒、文字列はGo duration形式(“5s”、“1m”)。

local ok, err = client:send("Hello, Server!")
if err then
return nil, err
end
-- JSONを送信
client:send(json.encode({
type = "subscribe",
channel = "orders"
}))
client:send(binary_data, websocket.BINARY)
パラメータ説明
datastringメッセージ内容
typenumberwebsocket.TEXT(1)またはwebsocket.BINARY(2)

戻り値: boolean, error

client:ping()

戻り値: boolean, error

channel()メソッドはメッセージ受信用のチャネルを返す。receive()channel()のエイリアス。多重化のためにchannel.selectと連携。

local ch = client:channel()
local msg, ok = ch:receive()
if ok then
print("Type:", msg.type) -- "text"または"binary"
print("Data:", msg.data)
end
local ch = client:channel()
while true do
local msg, ok = ch:receive()
if not ok then
break -- 接続がクローズ
end
if msg.type == "text" then
local data = json.decode(msg.data)
handle_message(data)
end
end
local ch = client:channel()
local timeout = time.after("30s")
while true do
local r = channel.select {
ch:case_receive(),
timeout:case_receive()
}
if r.channel == timeout then
client:ping() -- Keep-alive
timeout = time.after("30s")
else
local data = json.decode(r.value.data)
process(data)
end
end
フィールド説明
typestring"text"または"binary"
datastring?メッセージ内容(不明なペイロードタイプの場合は nil)
-- 通常のクローズ(コード1000)
client:close()
-- コードと理由を指定
client:close(websocket.CLOSE_CODES.NORMAL, "Session ended")
-- エラークローズ
client:close(websocket.CLOSE_CODES.INTERNAL_ERROR, "Processing failed")
パラメータ説明
codenumberクローズコード(1000-4999)、デフォルト1000
reasonstringクローズ理由(オプション)

戻り値: boolean, error

-- 数値(送信用)
websocket.TEXT -- 1
websocket.BINARY -- 2
-- 文字列(受信メッセージのtypeフィールド)
websocket.TYPE_TEXT -- "text"
websocket.TYPE_BINARY -- "binary"
websocket.TYPE_PING -- "ping"
websocket.TYPE_PONG -- "pong"
websocket.TYPE_CLOSE -- "close"
websocket.COMPRESSION.DISABLED -- 0(圧縮なし)
websocket.COMPRESSION.CONTEXT_TAKEOVER -- 1(スライディングウィンドウ)
websocket.COMPRESSION.NO_CONTEXT -- 2(メッセージごと)
定数コード説明
NORMAL1000正常終了
GOING_AWAY1001サーバーシャットダウン
PROTOCOL_ERROR1002プロトコルエラー
UNSUPPORTED_DATA1003サポートされていないデータ型
RESERVED1004予約済み
NO_STATUS1005ステータスを受信していない
ABNORMAL_CLOSURE1006接続が切断
INVALID_PAYLOAD1007無効なフレームペイロード
POLICY_VIOLATION1008ポリシー違反
MESSAGE_TOO_BIG1009メッセージが大きすぎる
MANDATORY_EXTENSION1010必須拡張がネゴシエートされていない
INTERNAL_ERROR1011サーバーエラー
SERVICE_RESTART1012サーバー再起動中
TRY_AGAIN_LATER1013サーバー過負荷
BAD_GATEWAY1014ゲートウェイエラー
TLS_HANDSHAKE1015TLSハンドシェイク失敗
client:close(websocket.CLOSE_CODES.NORMAL, "Done")
local function connect_chat(room_id, on_message)
local client, err = websocket.connect("wss://chat.example.com/ws", {
headers = {["Authorization"] = "Bearer " .. token}
})
if err then
return nil, err
end
-- ルームに参加
client:send(json.encode({
type = "join",
room = room_id
}))
-- メッセージループ
local ch = client:channel()
while true do
local msg, ok = ch:receive()
if not ok then break end
local data = json.decode(msg.data)
on_message(data)
end
client:close()
end
local client = websocket.connect("wss://stream.example.com/prices")
client:send(json.encode({
action = "subscribe",
symbols = {"BTC-USD", "ETH-USD"}
}))
local ch = client:channel()
local heartbeat = time.after("30s")
while true do
local r = channel.select {
ch:case_receive(),
heartbeat:case_receive()
}
if r.channel == heartbeat then
client:ping()
heartbeat = time.after("30s")
elseif not r.ok then
break -- 接続がクローズ
else
local price = json.decode(r.value.data)
update_price(price.symbol, price.value)
end
end
client:close()

WebSocket接続はセキュリティポリシー評価の対象。

アクションリソース説明
websocket.connect-WebSocket接続を許可/拒否
websocket.connect.urlURL特定のURLへの接続を許可/拒否

ポリシー設定についてはセキュリティモデルを参照。

条件種別再試行可能
接続が無効化errors.PERMISSION_DENIEDno
URLが許可されていないerrors.PERMISSION_DENIEDno
コンテキストがないerrors.INTERNALno
接続失敗errors.INTERNALyes
無効な接続IDerrors.INTERNALno
local client, err = websocket.connect(url)
if err then
if errors.is(err, errors.PERMISSION_DENIED) then
print("Access denied:", err:message())
elseif err:retryable() then
print("Temporary error:", err:message())
end
return nil, err
end

エラーの処理についてはエラー処理を参照。