2

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.

Community
  • 1
  • 1
Fratt
  • 239
  • 3
  • 13

1 Answers1

4

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)
}
halbgut
  • 2,368
  • 17
  • 22
  • This is great and thanks for the suggestion but is there a way to intercept RPC calls at the server? Meteor.connection appears to only be available at the client. – Fratt Sep 07 '15 at 14:08
  • Nothing that can't be found out with a little digging. I edited my answer. Could you maybe edit your question to include a clear question? – halbgut Sep 07 '15 at 21:35
  • Well...I just emphasized parts of the original question if that makes it clearer. I'll play around with your findings and see if it provides what I was looking for. Thanks again. – Fratt Sep 07 '15 at 23:27
  • From what I can tell, I can intercept the start of a connection session at the server using Kriegslustig's suggestion but can't intercept calls after that. I haven't found anything in the Meteor.server object structure to catch the individual DDP method requests at the transport level (DDP layer) prior to the methods actually being invoked :-( – Fratt Sep 08 '15 at 20:26