Skip to content

Instantly share code, notes, and snippets.

@3rd-Eden
Created August 26, 2014 19:34
Show Gist options
  • Save 3rd-Eden/6d150687d7a5d2696507 to your computer and use it in GitHub Desktop.
Save 3rd-Eden/6d150687d7a5d2696507 to your computer and use it in GitHub Desktop.
12:55:01 PM <omnidan> hi
12:55:58 PM ⇐ therealkoopa quit ([email protected]) Ping timeout: 255 seconds
12:56:07 PM <omnidan> is it possible to get the query in the authorization middleware without having a http server running? e.g. directly connecting from a nodejs primus client to a primus server
12:56:29 PM <omnidan> also, is it possible to connect with a socket.io-client to primus with socket.io in the backend?
1:06:03 PM → __quim_ and Kullt2 joined ⇐ __quim and Kullt quit ↔ therealkoopa popped in
1:34:29 PM <_3rdEden> hi
1:35:05 PM <_3rdEden> How would you get a request to your server when there isn't a server running omnidan ?
1:35:51 PM <_3rdEden> omnidan: it should be possible to connect with a socket.io-client to a primus + socket.io backend
1:36:00 PM <omnidan> _3rdEden: well there is a http server running, but I'm connecting via nodejs directly to primus, so it doesn't /use/ the server
1:36:13 PM <omnidan> at least I think so, I'm not familiar with the internals
1:36:23 PM <_3rdEden> The only thing you probably would need to change is the resource or pathname it connects to
1:36:35 PM <omnidan> my question is, how do I get the query in the authorization function?
1:36:36 PM <_3rdEden> which we default to /primus
1:37:15 PM <_3rdEden> When you connect from node to your primus server you probably use 2 differen node process, 1 for the client 1 for the server. So they need to use HTTP in order to connect with each other
1:37:22 PM <_3rdEden> so there is no way around it.
1:37:47 PM <_3rdEden> and with query you mean the querystring?
1:37:53 PM <_3rdEden> You can parse that out of the req.url
1:37:55 PM <omnidan> spark.query
1:37:58 PM <omnidan> hm
1:39:16 PM <omnidan> _3rdEden: so using socket.io-client to connect to primus + socket.io by doing io.connect("http://localhost:8080", {query: "session=test"});
1:39:27 PM <_3rdEden> var qs = require('querystring'); primus.authorize(function (req, next) { req.query = req.query || qs.parse(req.url); if (req.query.foo) next(); else next(new Error('damn'))
1:39:38 PM <omnidan> ok, that makes sense
1:39:46 PM <_3rdEden> omnidan: you can also create a client directly from Primus
1:39:51 PM <omnidan> so it always uses http, I see
1:40:05 PM <omnidan> _3rdEden: yeah but it should work with socket.io-client, right?
1:40:48 PM <_3rdEden> yes
1:41:26 PM <omnidan> hmm weird, it doesn't work for me
1:41:26 PM <_3rdEden> https://github.com/primus/primus#connecting-from-the-server
1:41:34 PM <_3rdEden> might also be helpful for you
1:41:44 PM <omnidan> _3rdEden: but that uses primus
1:42:04 PM <_3rdEden> i'll see if I can gist up an example without primus :p
1:42:07 PM ⇐ lpin quit ([email protected]) Quit: Textual IRC Client: www.textualapp.com
1:45:43 PM <omnidan> _3rdEden: thanks a lot, I'm actually considering primus because I'm currently having two issues with socket.io/engine.io, on engine.io (or socket.io 1.0), it doesn't send the ip address in the authentication middleware when connecting with socket.io-client (it does when connecting with a web client)
1:46:04 PM <omnidan> and on socket.io 0.9 (and engine.io/socket.io 1.0 too) I am sometimes having issues connecting to the server from a node.js client
1:46:13 PM <omnidan> it doesn't emit any event, it simply doesn't connect
1:46:36 PM <omnidan> and all this is just kind of confusing
1:47:33 PM <omnidan> and I thought it doesn't send the ip address when connecting with nodejs because that doesn't switch protocols like it does on the web, but if the socket.io client in nodejs uses http too, I don't really understand why this is happening
1:52:47 PM <_3rdEden> https://gist.github.com/3rd-Eden/2b3d2da88f9006219835
close3rd-Eden — 24 Jul 2014 2 files…
1
2
3
4
5
6
7
8
9
10
11
12
13
'use strict';
var io = require('socket.io-client');
var client = io.connect('http://localhost:1337', {
'resource': 'primus',
'force new connection': true,
'query': 'session='+ Date.now()
});
client.on('connect', function () {
console.log('connected');
});
view rawclient.js hosted with ❤ by GitHub
1:52:57 PM <_3rdEden> This works -- BUT
1:53:09 PM <_3rdEden> You need to manually send ping packets to the primus server
1:53:14 PM <_3rdEden> or you will be disconnected after 30 seconds
1:53:18 PM <omnidan> 'resource': 'primus',
1:53:18 PM <omnidan> 'force new connection': true,
1:53:19 PM <omnidan> hm
1:53:29 PM <_3rdEden> Yes
1:53:39 PM <_3rdEden> fixes a couple of socket.io bugs
1:53:52 PM <omnidan> what does "force new connection" do?
1:54:12 PM <_3rdEden> socket.io uses a horrible connection pool
1:54:28 PM <_3rdEden> this bypasses it
1:54:57 PM <_3rdEden> because it wants to multiplex connections
1:55:08 PM <_3rdEden> so when you connect for the first time, it works all fine and dandy
1:55:19 PM <_3rdEden> then you disconenct and want to connect again
1:55:22 PM <_3rdEden> it doesn't work
1:55:33 PM <_3rdEden> because it re-uses the connection which is closed
1:55:37 PM <_3rdEden> @_@
1:55:50 PM <_3rdEden> Which is why I advice you to use the Primus wrapper for the client as well
1:56:03 PM <_3rdEden> because we fixed all these horrible bugs and edgecases
1:56:07 PM <omnidan> _3rdEden: so about these issues I described above, could this be the connection issue?
1:56:10 PM <omnidan> I'm having
1:56:31 PM <omnidan> actually I think my connection issue might be a handshake error which socket.io 1.0 does not forward to the client for some reason ._.
1:56:32 PM <_3rdEden> Yes, most likely
1:56:40 PM <omnidan> well, it's a mix
1:56:47 PM <omnidan> so basically, just use primus :P
1:56:52 PM <_3rdEden> in addition to that socket.io reconnect is horribly broken
1:57:04 PM <_3rdEden> which is why we've disabled it by default and wrote our own
1:57:21 PM <omnidan> _3rdEden: so if I use primus and websockets without socket.io, will I still be able to get the ip address, query and automatic reconnect (or well, I could implement that myself too, that's not a problem)
1:57:34 PM <_3rdEden> yes
1:57:53 PM <_3rdEden> And you have trouble getting the ip address.. you might want to check out https://github.com/primus/forwarded-for
1:58:00 PM <_3rdEden> which normalizes ip addresses locations
1:58:23 PM <_3rdEden> This is something we do AFTER authorization in primus
1:58:42 PM <omnidan> ok hm
1:58:46 PM <_3rdEden> But maybe we should just do this "before"
1:58:52 PM <_3rdEden> everything else is done
1:59:05 PM <_3rdEden> so you can just have a req.forwarded.ip
1:59:13 PM <omnidan> _3rdEden: the thing is, I'm thinking about adding a connection limit by ip and disconnecting after it's already connected doesn't seem like the best solution
1:59:17 PM <_3rdEden> which will always contain the correct ip adress ._.
1:59:34 PM <_3rdEden> The obvious problem with that is proxy networks
1:59:50 PM <_3rdEden> corporate networks usually have one outgoing ip for all uses
1:59:53 PM <_3rdEden> users*
2:00:02 PM <omnidan> hm
2:00:09 PM <_3rdEden> so if you implement that, only one user can connect :)
2:00:23 PM <omnidan> I see
2:00:47 PM <omnidan> _3rdEden: but every time something is trying to authorize it sends a request to the authorization server, and I don't really want them to spam that :P
2:01:03 PM <omnidan> authorization server checks the session which is sent by query
2:02:14 PM <_3rdEden> Yep, and with primus we call the authorization for every, single, request
2:02:32 PM <_3rdEden> even http polling requests from transports
2:02:59 PM <_3rdEden> because this is more secure and prevents people from stealing sessions
2:03:15 PM <omnidan> so how do I prevent them from spamming that?
2:03:36 PM <omnidan> I guess I could set the limit per ip to 100 or something
2:03:49 PM <omnidan> I just don't want anybody to connect like 1 mio clients
2:03:55 PM <omnidan> and make them all authorize
2:05:09 PM <_3rdEden> You're basically trying to build something to prevent a possible DDOS attack
2:05:20 PM <_3rdEden> Why don't just add a rate limiter or something?
2:05:33 PM <omnidan> hm yeah
2:05:42 PM <_3rdEden> ip address X can only send x amount of requests per second
2:05:45 PM <omnidan> probably a better solution
2:06:30 PM <_3rdEden> if time since last request < x amount of ms, setTimeout(authorizatione, 10000) or kill the connection.
2:07:06 PM <omnidan> and then I could do a connection limit per client, like 3 sockets on a specific client (session resolves to client)
2:07:21 PM <_3rdEden> yeah
2:08:41 PM <omnidan> "if time since last request" how do I get the ip address then?
2:08:47 PM <omnidan> assuming you mean authorization requests
2:09:49 PM <omnidan> _3rdEden ^
2:10:30 PM <_3rdEden> Yes, you could do it based on IP address, or maybe come up with a unique ID on the client (which is more fragile)
2:10:57 PM <_3rdEden> In primus, i would just use forward-for and run it over the incoming request to get the ip address
2:11:56 PM <omnidan> _3rdEden: so var address = forwarded(req, req.headers); within authroization?
2:12:06 PM <_3rdEden> If I had more time today I would just move the forward-for logic as middleware in primus and be done with it
2:12:25 PM <_3rdEden> bleh, it's only 2 minutes of my time ._. i'll do it right away.
2:12:41 PM <_3rdEden> omnidan: exactly
2:13:20 PM <omnidan> ok thanks a lot, _3rdEden, you really helped me understand primus (and socket.io, and websockets in general) better :P it can be confusing at times
2:18:31 PM <_3rdEden> definitely, real-time can be pretty darn hard.
2:21:29 PM <omnidan> _3rdEden: well in theory it's simple, I just didn't know that socket.io-client, for example, also connects to the http server first and that's why you need one
2:38:05 PM → primus`github joined ↔ therealkoopa popped in
2:43:52 PM <primus`github> [primus] 3rd-Eden pushed 1 new commit to master: https://github.com/primus/primus/commit/d5ff8deea8d546febbd5dc2901d00c550d0691cc
2:43:52 PM <primus`github> primus/master d5ff8de 3rd-Eden: [minor] pre-parse the incoming HTTP requests before we pass them to authorization.
2:43:52 PM → therealkoopa joined ← primus`github left ⇐ vwoo quit
2:49:40 PM <omnidan> _3rdEden: so in socket.io I get the socket in the authorization function, in primus the socket isn't available yet when authorization is called, right?
2:49:49 PM ⇐ therealkoopa quit ([email protected]) Ping timeout: 255 seconds
2:50:06 PM <_3rdEden> omnidan: correct, you get the plain request
2:50:30 PM <_3rdEden> but in socket.io you used to get a handshake object
2:50:36 PM <_3rdEden> with some whitelisted details and data
2:50:38 PM <omnidan> hm, because I am using the socket.id to match the request later
2:50:52 PM <_3rdEden> why not use the session id to match it?
2:51:11 PM <_3rdEden> (from the query string)
2:51:44 PM <omnidan> yeah, I will, was just making sure it's just the request :P
2:54:13 PM <_3rdEden> :D
2:56:59 PM <omnidan> _3rdEden: should I still use this? https://github.com/primus/forwarded-for
2:57:00 PM <omnidan> for now
2:57:26 PM <omnidan> btw in your example you made a typo
2:57:26 PM <omnidan> 'use stict';
2:57:58 PM <_3rdEden> omnidan: I added the forwarded property in the master repo so it willl be there for the next release
3:00:45 PM <omnidan> ok
3:00:50 PM <omnidan> _3rdEden: well damn, I can't use the session
3:00:55 PM <omnidan> is there anything like socket.id I could use?
3:01:05 PM <omnidan> something primus uniquely assigns to both, the socket and the request/
3:03:12 PM → therealkoopa joined ([email protected])
3:03:39 PM <_3rdEden> Also corrected the use strict in the example.
3:03:53 PM <omnidan> _3rdEden: like, can I get the spark.id from the request?
3:03:59 PM <_3rdEden> The id of the connection isn't know yet when we authorize it
3:04:07 PM <_3rdEden> That all happens after the fact.
3:04:12 PM <omnidan> hm :/
3:04:18 PM <_3rdEden> Why not add another unique id?
3:04:31 PM <omnidan> how would I add it to the spark from the request?
3:04:43 PM <_3rdEden> in the spark you also have access to the querystrings
3:04:44 PM <omnidan> I don't have it yet in the authorization part
3:04:47 PM <_3rdEden> spark.query
3:05:13 PM <omnidan> the session querystring isn't always set :/
3:05:29 PM <omnidan> in socket.io I just did socket.id in authorization and socket.id in connection
3:06:47 PM <omnidan> _3rdEden ^
3:06:52 PM <_3rdEden> But you can set another uniq id, even if you don't have a session id
3:07:06 PM <omnidan> yes, but how do I assign it to the socket/spark within authorization?
3:07:17 PM <omnidan> doing it via querystring would be kinda hackish, wouldn't it/
3:07:28 PM <omnidan> like what if the client overwrites that :P
3:07:37 PM <_3rdEden> You don't assing it to a socket, it's just a way of identifing a client
3:07:53 PM <_3rdEden> The client can't really override a query string
3:08:11 PM <_3rdEden> and querystrings are a common practise of sending data to the server
3:08:15 PM <omnidan> see, I'm creating a client object within the authorization function, then later in the connection event I want to get that object I created in authorization
3:08:23 PM <_3rdEden> it's one of the most reliable ways (better then cookies for example)
3:08:31 PM <omnidan> but if the client can SOMEHOW spoof that id, that's gonna be a problem
3:08:58 PM <omnidan> because in authorization I'm pulling data from the authorization server that I want to use later in connection
3:09:09 PM <omnidan> and when it sends messages
3:09:10 PM <omnidan> etc
3:09:18 PM <_3rdEden> sure, but you also had that issue with socket.io
3:09:28 PM <_3rdEden> as your socket.io could also be spoofed
3:09:37 PM <_3rdEden> socket.id*
3:09:48 PM <omnidan> hm
3:09:53 PM <omnidan> what should I do, then?
3:10:37 PM <_3rdEden> I don't know
3:10:56 PM <_3rdEden> I got the feeling you're just over complicating everything because you don't want to hit the authorization server
3:11:05 PM <omnidan> hm
3:11:46 PM <_3rdEden> If the authorization server cannot handle the amount of requests, it might make more sense to fix that instead of applying all kinds of hacks on your real-time server
3:12:01 PM <omnidan> well it's not about the amount of requests
3:12:11 PM → •lpin (opped) joined
3:12:36 PM <omnidan> _3rdEden: I just want the client to be able to connect to the real time server with the same session it used on another server
3:12:53 PM <omnidan> on the real time server I send a request to the other server (amount of requests doesn't matter atm)
3:13:12 PM <omnidan> that tells me if the session is valid and gives me info about the client
3:14:23 PM <_3rdEden> And you're doing that by sending the session id using a query string
3:14:32 PM <omnidan> yup
3:15:08 PM <_3rdEden> But in your authorization handler you can just check the server to see if it's allowed or not and accept/deny the request
3:15:44 PM <_3rdEden> So you're already doing everything you said you were doing ._.
3:15:57 PM <_3rdEden> wanting to do*
3:16:14 PM <_3rdEden> But I really need to write some code now, sorry ._.
3:16:17 PM <omnidan> I'm kinda confused
3:16:26 PM <_3rdEden> you can ask the question in the issue track to see if someone else can help you out
3:16:27 PM <omnidan> ok
3:20:04 PM <•lpin> omnidan what's the prob?
3:21:07 PM <omnidan> lpin: I think there isn't a problem anymore
3:21:27 PM <omnidan> I just need to read through the primus documentation a bit and then adjust my code
3:23:13 PM <•lpin> ok, got some time atm so just ask if something isn't clear enough
3:23:28 PM <omnidan> thanks a lot, this community is really helpful :P
3:37:22 PM <omnidan> lpin: ok so I'm sending the session in the query string every time, in authorization I get the client data and connect it with the session on server side, so every time the client sends me a message, I know which client it is, does that sound good? :P
3:37:44 PM <omnidan> because the client always sends the session in the query string
3:39:02 PM <•lpin> yes, in the authorization hook you can identify your client and decide to close or eanble the connection
3:39:35 PM <•lpin> once the authorized connestion has been established you can start sending the data
3:41:56 PM <•lpin> and that's correct you can identify your client using a query string param like a token or something like that
4:09:17 PM <omnidan> lpin: can I generate that token automatically on the server and then assign it to the client, sort of like a session id?
4:09:38 PM <omnidan> I tried req.query.session = 'test'; in authorize and it doesn't seem to work
4:10:54 PM <•lpin> omnidan yes but you shouldn't do thta in the auth hook
4:11:04 PM <omnidan> so where should I do that?
4:11:17 PM <•lpin> there is an example in the primus repo
4:11:23 PM <•lpin> take a look at that
4:11:37 PM <omnidan> the authorization example?
4:11:38 PM <omnidan> ok
4:14:08 PM <omnidan> lpin: I'm just curious, why does primus send you the request in authorization and socket.io the socket?
4:15:20 PM <•lpin> primus takes a plain request before passing it to the underlying transformer
4:16:24 PM <•lpin> can't even rember what was the signature of socket.io authorization handler
4:16:26 PM <•lpin> :)
4:18:19 PM <omnidan> lpin: well it was easier for me with socket.io :/
4:19:04 PM <•lpin> omnidan it should be the same what were you doing in socket.io?
4:19:23 PM <•lpin> i mean in the socket.io auth handler
4:19:51 PM <omnidan> lpin: well in socket.io I did (not sure if that's a good solution, though)... authorize - send request to authorization server, get token (client data) - set socket.token and use socket.id and socket.token for checking which socket is which client
4:20:13 PM <omnidan> then on connect and on message I could just tell which client it is by using socket.id and socket.token
4:20:21 PM <omnidan> in primus this seems much harder to do
4:21:45 PM <omnidan> in primus I don't have the socket.id in authorization yet, I have to set my own id and then later connect that to the spark.id
4:24:36 PM <•lpin> why you need an id in the authorization?
4:25:12 PM <•lpin> is that the session id?
4:25:36 PM <omnidan> yes
4:25:45 PM <omnidan> I don't really have a session like that
4:26:14 PM <omnidan> lpin: basically all I want is to have the authorization handler work like it does in socket.io
4:26:38 PM <omnidan> if I could access spark.id in the authorization handler there wouldn't be a problem at all, but I do understand why I can't
4:26:42 PM <omnidan> so I'm trying to find a way around that
4:27:00 PM ⇐ therealkoopa quit ([email protected]) Remote host closed the connection
4:27:02 PM <•lpin> your session id is bound to the request not the spark
4:27:20 PM <•lpin> e.g. req.cookie.sessionid
4:27:29 PM <•lpin> or req.query.token
4:28:16 PM <_3rdEden> Socket.IO doesn't seem to give you the socket id either; https://github.com/Automattic/socket.io/blob/0.9/lib/manager.js#L856-L865
4:28:27 PM ⇐ Nicolab quit (~nicolas@unaffiliated/nicolab) Ping timeout: 256 seconds
4:28:44 PM <_3rdEden> The id is generated after you've authorized: https://github.com/Automattic/socket.io/blob/0.9/lib/manager.js#L801-L805
4:29:42 PM <•lpin> omnidan put your old authorization in a gist i'll try to help you convert it to primus
4:29:56 PM <omnidan> ok hold on
4:31:09 PM <omnidan> lpin: that's gonna take a while because this is part of a bigger project and makes calls to other classes ._.
4:31:38 PM <•lpin> sure, reduce it to the min
4:36:58 PM → s3shs and Nicolab joined
4:38:37 PM <omnidan> lpin: https://gist.github.com/omnidan/1e4b05d77dce372709ce
4:38:40 PM <omnidan> I hope this is understandable
4:39:57 PM <omnidan> lpin: I am connecting to this server from a nodejs client, btw, which only has the session
4:39:59 PM <•lpin> omnidan is this socket.io 1.0.x?
4:40:02 PM <omnidan> yes
4:40:09 PM <omnidan> but it worked on 0.9 too
4:40:26 PM <omnidan> I just used the migration tutorial
4:40:32 PM <omnidan> *guide
4:43:46 PM <•lpin> do you still have the 0.9 version?
4:44:30 PM <omnidan> next is different and this.io.authorize(function(socket, next) afaik
4:44:32 PM <omnidan> that's the only difference
4:44:33 PM <omnidan> lpin ^
4:44:56 PM <omnidan> I don't have a 0.9 version of that code, because I just abstracted that from the whole code I have here
4:45:21 PM <•lpin> ok
4:45:45 PM <omnidan> but do you understand my problem? I somehow need to identify the socket during authorization
4:46:06 PM <omnidan> it would be okay if I could like, set an id during authorization which is later used in the socket (I think that's how socket.io does it tbh)
4:46:10 PM <omnidan> lpin ^
4:47:40 PM <•lpin> what i understand there is that a token can be shared by multiple clients and you need to identify the clients that use the same token
4:47:57 PM <•lpin> correct me if i'm wrong
4:48:40 PM <omnidan> lpin: every client has a socket, that socket has an id, that socket.id is right now (in socket.io) the client id (so I can identify clients/sockets) - now I group those clients by a token
4:48:55 PM <omnidan> so to find a client by just the socket I do clients[socket.token][socket.id]
4:50:14 PM <•lpin> ok
4:51:42 PM <•lpin> you unique identifier is the id you get from socket.id
4:52:22 PM → therealkoopa joined ([email protected])
4:52:42 PM <omnidan> yes, lpin
4:52:57 PM <•lpin> you don't have it out of the box in primus
4:53:25 PM <omnidan> lpin: I've never worked with primus before so... how would I start doing that?
4:57:22 PM <•lpin> i would create an auth system where your client request a unique authorizion token
4:58:00 PM <•lpin> and save it in a cookie or send it as a query string to the primus server
4:58:07 PM <omnidan> lpin: but how does it request it? all I'm doing is connect to primus, it only triggers the authorization handler
4:58:27 PM <omnidan> so from the authorization handler, I somehow have to assign that unique id to the socket
4:58:29 PM <omnidan> but how?
4:58:38 PM <•lpin> you do a specific request before connecting
4:58:42 PM <•lpin> t primus
4:58:46 PM <omnidan> :/
4:58:52 PM <•lpin> to your auth server
4:58:58 PM <omnidan> that's not really the best solution
4:59:01 PM <omnidan> imo
4:59:12 PM <omnidan> I'd have to change something that already works fine
4:59:22 PM <omnidan> and it did work with socket.io, so?
4:59:58 PM <omnidan> the only problem with socket.io is that I have problems with the ip address and connections in general
5:03:28 PM <•lpin> omnidan how do you generate socket.handshake.query.session
5:04:25 PM <omnidan> lpin: well there's either .query.session or .query.app_key so I can't use session as a unique identifier
5:04:28 PM <omnidan> I need to use something else
5:05:57 PM <_3rdEden> So, you're not using Socket.IO's authorization but Socket.IO's middleware
5:06:02 PM <_3rdEden> which is completely different ._.
5:07:08 PM <omnidan> _3rdEden: oh hm, I used authorization before but they removed that in 1.0 and I did some refactoring when I ported it to 1.0, so I guess I didn't have the id before
5:07:09 PM <omnidan> you're right
5:07:15 PM <omnidan> sorry :<
5:07:18 PM <omnidan> I didn't think of that
5:07:43 PM <_3rdEden> Socket.IO middleware is just a function that is executed when a new connection is made
5:08:06 PM <_3rdEden> so you might as well add an addition connection listener and the same checks, and add properties that you need
5:09:00 PM <_3rdEden> orrr am I wrong here
5:10:37 PM ⇐ __quim_ quit ([email protected]) Quit: Leaving...
5:11:11 PM <omnidan> oh I see, _3rdEden
5:11:15 PM <omnidan> that makes sense
5:11:37 PM <omnidan> _3rdEden: but socket.io 1.0 dropped the authorization handler completely
5:11:44 PM <_3rdEden> not really
5:11:58 PM <_3rdEden> they have some sort of hook in to engine.io
5:12:05 PM <_3rdEden> which will be called.
5:12:28 PM <omnidan> The old io.set() and io.get() methods are deprecated and only supported for backwards compatibility. Here is a translation of an old authorization example into middleware-style.
5:12:35 PM <omnidan> _3rdEden ^
5:12:40 PM <omnidan> so yes it's there
5:12:44 PM <_3rdEden> lpin: do you think it makes sense to change this: https://github.com/primus/primus/blob/master/spark.js#L283 to asyncEmit?
5:12:45 PM <omnidan> but only for backwards compatibility
5:13:17 PM <•lpin> _3rdEden mmm maybe
5:13:39 PM <_3rdEden> omnidan: sure, but the .get/set didn't really make that much sense as it was duplicate code in the socket.io code base
5:13:51 PM <_3rdEden> as the same options could have been provided directly when you created a socket.io server
5:14:13 PM <omnidan> _3rdEden: so that'd be primus.before('connect', function(socket, next)?
5:14:32 PM <•lpin> omnidan the only way to do what you are doing there is authenticate the client first, and authorize it later when connecting to primus
5:14:52 PM <_3rdEden> omnidan: those are middleware layers which are called "before" requests enter the Primus server (plain ol http requests)
5:15:15 PM <_3rdEden> If you want to modify sparks in primus you should use plugins
5:15:17 PM <•lpin> there is no way to authenticate on the fly
5:15:22 PM <omnidan> lpin, _3rdEden: ok, just help me with this... how do I convert the socket.io 1.0 middleware .use function to primus middleware?
5:15:26 PM <_3rdEden> https://github.com/primus/primus#plugins
5:15:59 PM <_3rdEden> omnidan: the problem is that you want to add data, async, when you receive a new connection
5:16:08 PM <_3rdEden> this is not supported in primus yet
5:16:19 PM <omnidan> oh
5:17:08 PM <•lpin> i would say that yours is more a way of grouping connection than an auth system
5:17:16 PM <•lpin> correct me if i'm wrong
5:17:24 PM <omnidan> lpin: you're probably right, yes
5:17:42 PM <omnidan> so I can do that in on(connection) and it would do the same thing socket.io does, right?
5:17:51 PM <•lpin> yep
5:17:56 PM <omnidan> ok that's cool
5:18:03 PM <omnidan> and kill the connection when it fails
5:18:11 PM <omnidan> that's basically what socket.io does?
5:18:14 PM <•lpin> yes that should wrk
5:18:24 PM <omnidan> hm, nice
5:18:39 PM → primus`github joined (~primus`[email protected])
5:18:39 PM <primus`github> [primus] 3rd-Eden pushed 1 new commit to master: https://github.com/primus/primus/commit/81319a44b0977044fbfa3e14419cdb2248b837fa
5:18:39 PM <primus`github> primus/master 81319a4 3rd-Eden: [fix] Allow async execution of the connection event to mimic socket.io's middleware
5:18:39 PM ← primus`github left (~primus`[email protected])
5:18:39 PM <_3rdEden> And now we can do same the thing as socket.io ._.
5:18:47 PM <omnidan> yayyy
5:18:48 PM <_3rdEden> yay, amazing code base
5:19:08 PM <•lpin> i gotta go
5:19:09 PM <•lpin> brb
5:19:48 PM <_3rdEden> So. now when you do...
5:19:59 PM <_3rdEden> primus.on('connection', function (spark, next) {});
5:20:03 PM <omnidan> yup
5:20:06 PM <_3rdEden> you get the same thing as io.use
5:20:10 PM <omnidan> I do understand that :P
5:20:25 PM <omnidan> I should really just read through the socket.io and primus code or something
5:20:28 PM <_3rdEden> BUT, exception!
5:20:41 PM <_3rdEden> You need to make sure that this one of the first listeners you add
5:20:54 PM <omnidan> that's fine though
5:21:01 PM <_3rdEden> or you cannot stop the connection event from actually happening normally
5:21:02 PM <omnidan> I only have one on('connection' listener
5:21:49 PM <omnidan> now I just need to wait for 2.3.1 :3
5:25:32 PM <_3rdEden> 2.4 actually
5:25:47 PM <omnidan> oh?
5:25:48 PM <_3rdEden> I'm writing tests and kicking out a release shortly after this
5:25:54 PM <omnidan> oh ok
5:26:05 PM <_3rdEden> Because in master we've added support for yet another transformer (faye websockets)
5:26:21 PM <_3rdEden> I don't consider this a minor change :)
5:26:59 PM <omnidan> yeah you're right
5:27:11 PM <omnidan> well thanks a lot
5:27:17 PM <omnidan> you guys are great, really
5:27:26 PM <omnidan> and sorry for the confusion with socket.io middleware/authorization >.<
5:42:21 PM <_3rdEden> :D
6:15:37 PM <_3rdEden> And it's out
6:15:45 PM → primus`github joined (~primus`[email protected])
6:15:45 PM <primus`github> [primus] 3rd-Eden pushed 4 new commits to master: https://github.com/primus/primus/compare/81319a44b097...0f52b5f4a3f1
6:15:45 PM <primus`github> primus/master 0d9d10a 3rd-Eden: [test] Fix broken integration tests
6:15:45 PM <primus`github> primus/master b32a898 3rd-Eden: [test] Add test for async execution of the `connection` event.
6:15:45 PM <primus`github> primus/master 7acb6c2 3rd-Eden: [doc] Added information about the new async execution
6:15:45 PM ← primus`github left (~primus`[email protected])
6:16:16 PM — _3rdEden goes away for dinner and writes release notes afterwards
6:34:08 PM → nodekid joined ↔ Flam and Fishrock123 popped in • Kullt2 → kullt
8:40:05 PM _3rdEden → `3rdEden
8:40:10 PM •`3rdEden was opped (+o) by •ChanServ
8:40:30 PM •`3rdEden set the topic: Primus - Transforming real-time since 2013: https://github.com/primus/primus — Latest version: 2.4 — News: 1.2k ★ reached on GitHub and counting
8:43:06 PM → vwoo and primus`github joined ⇐ lpin quit ↔ Flam popped in
9:44:03 PM <primus`github> [primus] lpinca pushed 1 new commit to master: https://github.com/primus/primus/commit/bf7782714bf255d04d9515f98c11d0277b7a0877
9:44:03 PM <primus`github> primus/master bf77827 Luigi Pinca: [typo] Fix a couple of typos
9:44:03 PM ⇐ vwoo quit ↔ primus`github nipped out
9:50:16 PM <primus`github> [primus] 3rd-Eden tagged 2.4.0 at master: https://github.com/primus/primus/commits/2.4.0
9:50:16 PM → travis-ci joined ← primus`github left
9:53:40 PM <travis-ci> [travis-ci] primus/primus#801 (2.4.0 - bf77827 : Luigi Pinca): The build passed.
9:53:40 PM <travis-ci> [travis-ci] Change view : https://github.com/primus/primus/compare/2.4.0
9:53:40 PM <travis-ci> [travis-ci] Build details : http://travis-ci.org/primus/primus/builds/30784186
9:53:40 PM → SomeKittens and nodekid_ joined ← travis-ci left ⇐ nodekid and s3shs quit ↔ Flam popped in
12:17:35 AM → vwoo, •lpin (opped), __quim and Kullt joined ⇐ kullt, therealkoopa and SomeKittens quit ↔ kmctown and s3shs popped in
12:15:18 PM → therealkoopa and primus`github joined ⇐ vwoo quit ↔ •lpin (opped) nipped out
3:31:21 PM <primus`github> [primus] lpinca pushed 1 new commit to master: https://github.com/primus/primus/commit/e12ab53a63a32179a1e189f8885e2ddd98669e59
3:31:21 PM <primus`github> primus/master e12ab53 Luigi Pinca: [codestyle] Fix some JSDoc comments...
3:31:21 PM → vwoo, nodekid and SomeKittens joined ← primus`github left ⇐ __quim, therealkoopa, lpin and nodekid_ quit ↔ mmalecki and Amec nipped out
12:08:45 AM → Bruun_, s3shs and __quim_ joined ⇐ vwoo, Bruun and nodekid quit ↔ therealkoopa, •lpin (opped), __quim and Fishrock123 popped in ↔ Kullt and SomeKittens nipped out
Sunday, July 27th, 2014
12:24:23 AM → nodekid and •lpin (opped) joined ⇐ s3shs and __quim_ quit ↔ therealkoopa popped in ↔ Kullt nipped out
2:20:59 PM ← Nicolab left ⇐ SomeKittens quit ↔ Daniela popped in
5:45:40 PM <omnidan> spark.emit('error', err); in spark.js:286 seems to fail (TypeError: Uncaught, unspecified "error" event.)
6:05:17 PM <omnidan> I updated the gist: https://gist.github.com/omnidan/fded853821c1043a716a
closeomnidan: primus test — 27 Jul 2014 3 files…
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!doctype html>
<html lang="en">
<head>
<title>Test</title>
<script src="/primus/primus.js"></script>
</head>
<body>
<script>
var primus = new Primus();
primus.on('open', function open() {
console.log('Connected.');
});
primus.on('data', function received(data) {
console.log(data);
});
primus.on('error', function error(err) {
console.error(err);
});
</script>
</body>
view rawindex.html hosted with ❤ by GitHub
6:22:33 PM → SomeKittens joined ↔ •lpin (opped) nipped out
7:25:50 PM <•lpin> omnidan do you have an error lister on your spark?
7:26:54 PM <omnidan> lpin: well not on the server, but on the client
7:27:00 PM <omnidan> the thing is, why does it need that?
7:27:13 PM <omnidan> I thought it emits the error to the client
7:27:17 PM <omnidan> like in socket.io :/
7:27:40 PM <•lpin> the error is emitted on the server, see https://github.com/primus/primus/blob/master/spark.js#L286
7:27:55 PM <•lpin> we should add a listener check there
7:28:00 PM <omnidan> that's not socket.io-like behaviour then, though
7:28:24 PM <omnidan> https://github.com/primus/primus/commit/81319a44b0977044fbfa3e14419cdb2248b837fa
7:28:37 PM <omnidan> > to mimic socket.io's middleware
7:29:13 PM <omnidan> in socket.io it doesn't trigger the on('connect') event in the client and just outputs a handshake error
7:32:15 PM <•lpin> i see, i'm not sure how to not trigger the `connection` event on the client
7:32:46 PM <omnidan> well that wouldn't be such a problem
7:33:06 PM <omnidan> as long as it sends the error to the client and doesn't crash when I don't have the listener on the server :P
7:35:50 PM <omnidan> lpin: so how do I send the error to the spark and trigger primus.on('error') in the client?
7:36:26 PM <•lpin> gime me a sec i'm fixing the crash
7:51:19 PM → primus`github joined (~primus`[email protected])
7:51:19 PM <primus`github> [primus] lpinca pushed 1 new commit to master: https://github.com/primus/primus/commit/4d1a0205db654dafdadf0adbd9415685ae6ecdf6
7:51:19 PM <primus`github> primus/master 4d1a020 Luigi Pinca: [fix] Emit the `incoming::error` event instead of `error` event
7:51:19 PM ← primus`github left (~primus`[email protected])
7:51:36 PM <•lpin> Should fix the crash
7:53:27 PM <omnidan> ok so
7:53:34 PM <omnidan> how do I forward the error to the client, lpin?
7:54:56 PM <•lpin> omnidan no easy way, or i can't think of an immediate solution
8:20:10 PM <•lpin> omnidan create an issue for that
8:22:11 PM <omnidan> https://github.com/primus/primus/issues/270
8:27:54 PM <omnidan> lpin: so what do I do for now?
8:33:42 PM <•lpin> i think that right now you can't distinguish and end on the client that was caused by that `next(err)` call from a normal end
8:39:16 PM <omnidan> lpin: but next(err); does spark.end();, so I could get the reason in on('data') and listen on on('disconnection') to see if the handshake failed?
8:41:38 PM <•lpin> you won't get any data on the client when calling `spark.end()` without an argument
8:42:24 PM <omnidan> eh
8:42:49 PM <omnidan> oh I see
8:42:50 PM <omnidan> so
8:43:08 PM <omnidan> lpin: here: https://github.com/primus/primus/commit/81319a44b0977044fbfa3e14419cdb2248b837fa#diff-ff6f7550d889ce29146e85ef3e8f192fR287 - that should be spark.end(err);?
8:44:19 PM <•lpin> yes that way your client will get it on the data listener
8:44:57 PM <omnidan> the way it is right now it doesn't make sense
8:45:14 PM <omnidan> why would I want to trigger an error on the server and then receive it on the server? the server already knows about the error
8:45:40 PM <•lpin> it wasn't done to forward the error on the client
8:46:08 PM <omnidan> but what's the point then?
8:46:32 PM <omnidan> that doesn't mimic socket.io behaviour and it doesn't even make sense, imo, at least
8:46:56 PM <•lpin> well honestly i see no point on forwarding it to the client but you have probably your use case
8:47:08 PM <omnidan> the point is to let the client know why it was rejected
8:48:04 PM <omnidan> I see no point in emitting the error to the spark
8:48:48 PM <omnidan> but maybe we should wait for `3rdEden
8:48:57 PM <•lpin> we should probably adjust this https://github.com/primus/primus/blob/master/primus.js#L800-L837 to forward the error
8:50:09 PM <•lpin> and do something like we do here https://github.com/primus/primus/blob/master/spark.js#L218
8:50:20 PM <•lpin> but yes, wait `3rdEden
8:50:34 PM <omnidan> hm yeah
8:53:28 PM <omnidan> lpin: actually this is what I want: http://socket.io/docs/server-api/#namespace#use(fn:function):namespace
8:53:37 PM <omnidan> a similar feature
8:54:44 PM <•lpin> "Errors passed to middleware callbacks are sent as special error packets to clients." <-- this needs to be implemented in primus
8:55:12 PM <•lpin> there is nothing like that
8:56:11 PM <omnidan> ok
8:56:54 PM <•lpin> add that to your open issue :)
8:57:13 PM <•lpin> it makes things easier to understand
8:57:46 PM <omnidan> https://github.com/primus/primus/issues/270
8:58:07 PM <•lpin> perfect :>
8:58:09 PM <•lpin> brb
8:58:20 PM *.net ↮ *.split → CtlAltDe1 joined ⇐ lpin and CtlAltDel quit ↔ vwoo and therealkoopa popped in ↔ beppu nipped out
12:14:44 AM → •lpin (opped) and __quim joined ⇐ SomeKittens quit ↔ vwoo popped in ↔ Kullt, timbur and dobson nipped out
12:22:49 PM <•`3rdEden> You can wait - but im not here omnidan / lpin. im on vacation atm ;)
12:23:06 PM <omnidan> oh ok
12:23:55 PM <•`3rdEden> Sending erreors from server to client seems a bit opinionated and a waste of bandwidth for normal usecases
12:24:34 PM <•`3rdEden> but it can be implemented using message transformers
12:25:07 PM <•`3rdEden> but idk
12:25:27 PM <•`3rdEden> ill think about it during my vacation ;)
1:32:18 PM <omnidan> `3rdEden: I think it depends on the kind of error. e.g. on spark.end()/disconnect the client should be able to know /why/ it was disconnected, right?
1:32:50 PM <omnidan> so does on('error') in the client actually do anything?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment