通过WebSocket连接AppSync订阅报错UnsupportedOperation求助
问题
通过WebSocket连接向AWS AppSync发送订阅请求时,收到错误:
{errorType: "UnsupportedOperation", message: "unknown not supported through the realtime channel"}
测试代码
let ws = undefined; const id = 'XXX'; const region = 'YYY'; const apikey = 'ZZZ'; const host = id + '.appsync-api.' + region + '.amazonaws.com'; const url = 'wss://' + id + '.appsync-realtime-api.' + region + '.amazonaws.com'; const httpUrl = 'https://' + host + '/graphql'; function openWebsocket(){ const api_header = { host: host, 'x-api-key': apikey, }; // payload should be an empty JSON object const payload = {}; const base64_api_header = btoa(JSON.stringify(api_header)); const base64_payload = btoa(JSON.stringify(payload)); const appsync_url = url + '?header=' + base64_api_header + '&payload=' + base64_payload; return new WebSocket(appsync_url, ['graphql-ws']); } function runWebsocket() { ws = openWebsocket(); /** * Send request over websocket * (Convenience function) */ const _send = (obj) => { ws.send(JSON.stringify(obj)); }; let initializingMode = true; ws.onopen = (e) => { // initialization phase start: _send({ type: 'connection_init' }); }; ws.onmessage = (e) => { const data = JSON.parse(e.data); if (initializingMode) { if (data.type == 'connection_ack') { // Acknowledge came, so we can start subscribing // try to subscribe { const query = { query: `subscription MySubscription { onCreateNotifications { creationTime userid } }`, }; const queryStr = JSON.stringify(query); _send({ id: localStorage.getItem(HeaderItems.idToken), type: 'start', payload: { data: queryStr, }, authorization: { host: host, 'x-api-key': apikey, }, }); } initializingMode = false; return; } } }; };
问题原因及修复方案
错误点1:payload.data格式错误
AppSync的start消息要求payload.data是解析后的JSON对象,而非JSON字符串。你当前把query对象转成字符串传递,导致服务端无法正确解析查询。
错误点2:多余的authorization字段
连接建立时已经通过URL参数传递了API Key授权信息,start消息里无需重复发送authorization字段,否则会导致服务端识别错误。
错误点3:start消息的id需为唯一标识
id字段是订阅会话的唯一标识,建议使用随机字符串或UUID,避免使用可能为空或不唯一的idToken。
修正后的代码
let ws = undefined; const id = 'XXX'; const region = 'YYY'; const apikey = 'ZZZ'; const host = id + '.appsync-api.' + region + '.amazonaws.com'; const url = 'wss://' + id + '.appsync-realtime-api.' + region + '.amazonaws.com'; const httpUrl = 'https://' + host + '/graphql'; function openWebsocket(){ const api_header = { host: host, 'x-api-key': apikey, }; const payload = {}; const base64_api_header = btoa(JSON.stringify(api_header)); const base64_payload = btoa(JSON.stringify(payload)); const appsync_url = url + '?header=' + base64_api_header + '&payload=' + base64_payload; return new WebSocket(appsync_url, ['graphql-ws']); } function runWebsocket() { ws = openWebsocket(); const _send = (obj) => { ws.send(JSON.stringify(obj)); }; let initializingMode = true; ws.onopen = (e) => { _send({ type: 'connection_init' }); }; ws.onmessage = (e) => { const data = JSON.parse(e.data); if (initializingMode) { if (data.type === 'connection_ack') { // 生成唯一订阅ID const subscriptionId = 'sub-' + Math.random().toString(36).substring(2, 15); const query = { query: `subscription MySubscription { onCreateNotifications { creationTime userid } }`, }; _send({ id: subscriptionId, type: 'start', payload: { data: query, // 直接传递对象,不用转字符串 }, // 移除多余的authorization字段 }); initializingMode = false; return; } } else { // 处理订阅返回的消息 if (data.type === 'data') { console.log('收到订阅数据:', data.payload.data); } else if (data.type === 'error') { console.error('订阅错误:', data.payload.errors); } } }; // 处理连接错误 ws.onerror = (error) => { console.error('WebSocket连接错误:', error); }; // 处理连接关闭 ws.onclose = (event) => { console.log('WebSocket连接关闭:', event); }; };
内容的提问来源于stack exchange,提问作者DarkTrick
相关产品推荐
相关产品推荐

