Fratt
Fratt

Reputation: 239

DDP call interception

I'm thinking of scenarios where I might want to perform cross-cutting/AOP or other functions at the server for my Meteor Js project when a Meteor client (or DDP client) invokes a server-side method over a DDP connection.

This link here gives a really nice example of how to perform AOP on objects, but I wanted to know if there was a way to listen for inbound client requests over the DDP connection much like express-interceptor or action filters for asp.net web api but, of course, for websocket/ddp rpc implementations.

The Meteor Js Api describes only one event "onConnection" at the server. And this SO response mentions a connection._send on the client to perform certain AOP functions...but didn't find a whole lot of official documentation beyond that.

I basically want to know if there is a way to listen at the server for all DDP method calls from all client sessions to the server as described in the DDP spec here

Thanks.

Upvotes: 2

Views: 1086

Answers (1)

halbgut
halbgut

Reputation: 2386

We'll there are a lot of undocumented things in Meteor you'll find. I don't really see it as a problem. Here are some ways to intercept WebSocket traffic in Meteor:

Server

Here's some stuff you can do from the server:

Server -> Client

It's a bit tedious to intercept messages from the server to the client, but this works. You'd probably want to write some code to pin logs to clients.

(function () {
  var timeout = 3000
  var streamServer = Meteor.server.stream_server
  var standardConnect = streamServer.server._events.connection

  streamServer.server._events.connection = function (socket) {
    var write = socket.write
    socket.write = function () {
      console.log(arguments)
      write.apply(this, args)
    }
    standardConnect.apply(this, arguments)
  }
})()

Client -> Server

To intercept calls from the client on the server you can do this:

Meteor.server.stream_server.server.addListener('connection', function (socket) {
  var old = socket._events.data
  socket._events.data = function () {
    console.log(arguments)
    old.apply(this, arguments)
  }
})

The above sipped can't be used with the first one. It's not hard to fix dough. If you use this snipped, Meteor.server.stream_server.server._events.connection will simply be an array of functions instead of a function.

Client

Server - > Client

To Listen to calls from server to the client on the client you can do this:

Meteor.connection._stream.on('message', console.log.bind(console))

You can also intercept them using something like this

(function () {
  var cb = Meteor.connection._stream.eventCallbacks.message[0]
  Meteor.connection._stream.eventCallbacks.message[0] = function () {
    console.log(arguments)
    cb.apply(this, arguments)
  }
})()

Not entirely sure how solid that one is. But it works, so what the heck.

To test it out you can simply do

Meteor.subscribe('test')

Client -> Server

As you pointed out, you can also do similar things with outgoing messages from the client.

Meteor.connection._send = function () {
  console.log(arguments)
  this.__proto__._send.apply(this, arguments)
}

Upvotes: 4

Related Questions