I’m trying to call a Meteor method over websocket, but I get a response saying
Malformed method invocation
The code is in Node.js and looks like this:
const WebSocket = require('ws')
let ws = undefined
let methodId = 1
function meteorConnect(host) {
var resolve, reject
const promise = new Promise((res, rej) => {resolve = res; reject = rej})
ws = new WebSocket(`ws://${host}/websocket`)
ws.on('open', () => {
ws.send(JSON.stringify({
msg: 'connect',
version: '1',
support: [ '1', 'pre2', 'pre1' ]
}))
})
const onconnect = msg => {
msg = JSON.parse(msg)
if (msg.msg && msg.msg == 'failed') reject(new Error('connection failed.'))
if (msg.msg && msg.msg == 'error') reject(new Error(msg.reason))
if (msg.msg && msg.msg == 'connected') {
//ws.off('message', onconnect)
resolve(msg.session)
}
}
const onping = msg => {
msg = JSON.parse(msg)
if (msg.msg && msg.msg == 'ping') {
ws.send(JSON.stringify({
msg: 'pong'
}))
setTimeout(() => {
ws.send(JSON.stringify({
msg: 'ping'
}))
}, 25000)
}
}
ws.on('message', onconnect)
ws.on('message', onping)
return promise
}
function meteorCall(methodName, ...args) {
var resolve, reject
const promise = new Promise((res, rej) => {resolve = res; reject = rej})
const currentMethodId = methodId++
ws.send(JSON.stringify({
msg: 'method',
method: methodName,
params: [...args],
id: currentMethodId,
}))
const onmethod = msg => {
msg = JSON.parse(msg)
if (msg.msg && msg.msg == 'failed') reject(new Error('Method call failed.'))
if (msg.msg && msg.msg == 'error') reject(new Error(msg.reason))
if (msg.msg && msg.msg == 'result' && msg.id == '8') {
console.log(' --- method result:', msg)
//ws.off('message', onmethod)
resolve(msg.result)
}
}
ws.on('message', onmethod)
}
meteorConnect('192.168.0.5:3000')
.then(sessionId => {
console.log('session ID:', sessionId)
return meteorCall('foo', 1, 2, 3)
})
.then(result => {
console.log('method result:', result)
})
.catch(e => {
throw e
})
What I did so far is look at Chrome’s Network tab and at the websocket frames to see what the client is sending when I use Meteor.call('foo', 1, 2, 3)
, but when I try to replicate that manually in the above program it fails, although I think my payload is exactly the same (except for the method id
which I’m incrementing for my session).
What am I missing?