I am running a SailsJS instance (v0.12.3) for which I have a controller MyModelController handling a WebSocket (socket.io
) connection that is allowed if the user has authenticated.
我正在运行一个SailsJS实例(v0.12.3),其中有一个控制器MyModelController,它处理一个WebSocket (socket.io)连接,如果用户进行了身份验证,该连接是允许的。
MyModelController
module.exports = {
/**
* Socket connection
*/
connect: function(req, res) {
/* Checks it's a socket connection request */
if (!req.isSocket) { return res.badRequest();}
/* Checks it's authenticated */
if (req.session.me) {
User.findOne(req.session.me, function (err, me) {
if (req.param('name')) {
MyModel.findOne({
name: req.param('name')
}).exec(function(err, objectFound) {
/* e.g. Join a room named after the params passed */
sails.sockets.join(req, objectFound.name);
return res.ok({ message: "All is OK!"}});
});
}
});
}
}
}
From a SailsJS served page e.g. myPage.ejs
, this works well:
从一个SailsJS服务页,例如myPage。ejs,这作品:
<!DOCTYPE html>
<html>
<head>...</head>
<body>
...
<script src="/js/dependencies/sails.io.js"></script>
<script src="/js/dependencies/app.io.js"></script>
<script src="/vendor/jquery/jquery.min.js"></script>
<script type "text/javascript">
// Use .get() to contact the server
io.socket.get('/myModel/connect?name=john', function gotResponse(body, response) {
console.log('Status code ' + response.statusCode + ' & data: ', body);
});
</script>
</body>
</html>
How do I connect to SailsJS socket.io server from a Python client?
In first my few attempts, I tried to leave the Authentication part for later. So let's say, we don't have to worry about it for now.
在最初的几次尝试中,我试图将身份验证部分留到以后。假设,我们现在不用担心这个。
I installed a Python socket.io client pip install socketIO-client-2
See socketIO-client-2 doc.
我安装了一个Python套接字。io客户端pip安装sockeot -client-2参见socketi -client-2 doc。
And for starters tried this (oh and BTW I am using a secured connection with self-signed certs):
对于初学者来说(哦,顺便说一句,我使用的是与自签名证书的安全连接):
from socketIO_client import SocketIO
SocketIO('https://localhost:1337/myModel/connect', params={'name': 'john'}, verify=False)
but then I get an error immediately on the Sails server side:
但是我马上在帆服务器端发现了一个错误:
verbose: Sending 400 ("Bad Request") response
with an error on the client side
在客户端出现错误
Failed to establish a new connection: [Errno 61] Connection refused
So I commented out the socket connection request and authenticated checks, to make it simpler, hoping to figure it out...
因此,我注释掉了套接字连接请求和经过身份验证的检查,以使它更简单,希望能够解决它……
connect: function(req, res) {
if (req.param('name')) {
MyModel.findOne({
name: req.param('name')
}).exec(function(err, objectFound) {
console.log(req.socket.id);
console.log(param('name'));
sails.sockets.join(req, objectFound.name);
return res.ok({ message: "All is OK!"}});
});
} else {
console.log('No params passed to the websocket');
}
}
which gives me on the Sails side:
这让我在帆的一边:
connect > found object: { name: 'john',
id: 1,
createdAt: '2016-11-04T15:20:38.000Z',
updatedAt: '2016-11-04T15:20:38.000Z' }
Socket request undefined <============== UNDEFINED
warn: Attempted to call `sailsSockets.join`, but the first argument was not a socket.
Socket Id: undefined
My Python log:
/usr/local/lib/python2.7/site-packages/requests/packages/urllib3/connectionpool.py:843: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
InsecureRequestWarning)
Traceback (most recent call last):
File "wsclient.py", line 17, in <module>
SocketIO('https://localhost:1337/myModel/connect', params={'name': 'john'}, verify=False)
File "/usr/local/lib/python2.7/site-packages/socketIO_client/__init__.py", line 334, in __init__
resource, hurry_interval_in_seconds, **kw)
File "/usr/local/lib/python2.7/site-packages/socketIO_client/__init__.py", line 51, in __init__
self._transport
File "/usr/local/lib/python2.7/site-packages/socketIO_client/__init__.py", line 59, in _transport
self._engineIO_session = self._get_engineIO_session()
File "/usr/local/lib/python2.7/site-packages/socketIO_client/__init__.py", line 73, in _get_engineIO_session
transport.recv_packet())
File "/usr/local/lib/python2.7/site-packages/socketIO_client/transports.py", line 81, in recv_packet
for engineIO_packet in decode_engineIO_content(response.content):
File "/usr/local/lib/python2.7/site-packages/socketIO_client/parsers.py", line 95, in decode_engineIO_content
content, content_index)
File "/usr/local/lib/python2.7/site-packages/socketIO_client/parsers.py", line 202, in _read_packet_length
while get_byte(content, content_index) not in [0, 1]:
File "/usr/local/lib/python2.7/site-packages/socketIO_client/symmetries.py", line 28, in get_byte
return six.indexbytes(x, index)
File "/usr/local/lib/python2.7/site-packages/six.py", line 655, in indexbytes
return ord(buf[i])
IndexError: string index out of range
Any pointers?
指针吗?
INTERESTING LINKS:
有趣的链接:
- how-to-connect-socket-io-client-to-sails-js-server, but that's using NodeJS
- 如何连接到socket-io-client- sails- server,但是这是使用NodeJS
- sails.io.js for nodejs
- sails.io。js对nodejs
When NodeJS + sails.io.js
I guess I want to achieve this, but in python
我想我想要实现这一点,但是在python中
var socketIOClient = require('socket.io-client');
var sailsIOClient = require('sails.io.js');
// Instantiate the socket client (`io`)
// (for now, you must explicitly pass in the socket.io client when using this library from Node.js)
var io = sailsIOClient(socketIOClient);
// Set some options:
// (you have to specify the host and port of the Sails backend when using this library from Node.js)
io.sails.url = 'http://localhost:1337';
// ...
// Send a GET request to `http://localhost:1337/hello`:
io.socket.get('/hello', function serverResponded (body, JWR) {
// body === JWR.body
console.log('Sails responded with: ', body);
console.log('with headers: ', JWR.headers);
console.log('and with status code: ', JWR.statusCode);
// When you are finished with `io.socket`, or any other sockets you connect manually,
// you should make sure and disconnect them, e.g.:
io.socket.disconnect();
// (note that there is no callback argument to the `.disconnect` method)
});
which gives this log when connecting
连接时,哪个给这个日志
$ DEBUG=* node sio-client.js
socket.io-client:url parse https://localhost:1337 +0ms
socket.io-client new io instance for https://localhost:1337 +5ms
socket.io-client:manager readyState closed +3ms
socket.io-client:manager opening https://localhost:1337 +0ms
engine.io-client:socket creating transport "websocket" +1ms
engine.io-client:socket setting transport websocket +29ms
socket.io-client:manager connect attempt will timeout after 20000 +0ms
socket.io-client:manager readyState opening +7ms
engine.io-client:socket socket receive: type "open", data "{"sid":"hj4FCwhk_pQ3hoTbAAAE","upgrades":[],"pingInterval":25000,"pingTimeout":60000}" +17ms
engine.io-client:socket socket open +0ms
socket.io-client:manager open +0ms
socket.io-client:manager cleanup +1ms
socket.io-client:socket transport is open - connecting +0ms
engine.io-client:socket socket receive: type "message", data "0" +215ms
socket.io-parser decoded 0 as {"type":0,"nsp":"/"} +0ms
socket.io-client:socket emitting packet with ack id 0 +3ms
socket.io-client:manager writing packet {"type":2,"data":["get",{"method":"get","headers":{},"data":{},"url":"/mymodel/connect?name=john"}],"options":{"compress":true},"id":0,"nsp":"/"} +0ms
socket.io-parser encoding packet {"type":2,"data":["get",{"method":"get","headers":{},"data":{},"url":"/mymodel/connect?name=john"}],"options":{"compress":true},"id":0,"nsp":"/"} +2ms
socket.io-parser encoded {"type":2,"data":["get",{"method":"get","headers":{},"data":{},"url":"/mymodel/connect?name=john"}],"options":{"compress":true},"id":0,"nsp":"/"} as 20["get",{"method":"get","headers":{},"data":{},"url":"/mymodel/connect?name=john"}] +0ms
engine.io-client:socket flushing 1 packets in socket +1ms
|> Now connected to Sails.
\___/ For help, see: http:
(using sails.io.js node SDK @v1.1.0)
engine.io-client:socket socket receive: type "message", data "30[{"body":{"mymodel":{"name":"john","id":1,"createdAt":"2016-11-04T15:20:38.000Z","updatedAt":"2016-11-04T15:20:38.000Z","assembly":"drive"},"message":"DRIVE, Joined room john"},"headers":{"Access-Control-Allow-Origin":"","Access-Control-Allow-Credentials":"","Access-Control-Allow-Methods":"","Access-Control-Allow-Headers":"","Access-Control-Expose-Headers":"","access-control-allow-origin":"","access-control-allow-credentials":"","access-control-allow-methods":"","access-control-allow-headers":"","access-control-expose-headers":""},"statusCode":200}]" +242ms
socket.io-parser decoded 30[{"body":{"mymodel":{"name":"john","id":1,"createdAt":"2016-11-04T15:20:38.000Z","updatedAt":"2016-11-04T15:20:38.000Z","assembly":"drive"},"message":"DRIVE, Joined room john"},"headers":{"Access-Control-Allow-Origin":"","Access-Control-Allow-Credentials":"","Access-Control-Allow-Methods":"","Access-Control-Allow-Headers":"","Access-Control-Expose-Headers":"","access-control-allow-origin":"","access-control-allow-credentials":"","access-control-allow-methods":"","access-control-allow-headers":"","access-control-expose-headers":""},"statusCode":200}] as {"type":3,"nsp":"/","id":0,"data":[{"body":{"mymodel":{"name":"john","id":1,"createdAt":"2016-11-04T15:20:38.000Z","updatedAt":"2016-11-04T15:20:38.000Z","assembly":"drive"},"message":"DRIVE, Joined room john"},"headers":{"Access-Control-Allow-Origin":"","Access-Control-Allow-Credentials":"","Access-Control-Allow-Methods":"","Access-Control-Allow-Headers":"","Access-Control-Expose-Headers":"","access-control-allow-origin":"","access-control-allow-credentials":"","access-control-allow-methods":"","access-control-allow-headers":"","access-control-expose-headers":""},"statusCode":200}]} +244ms
socket.io-client:socket calling ack 0 with [{"body":{"mymodel":{"name":"john","id":1,"createdAt":"2016-11-04T15:20:38.000Z","updatedAt":"2016-11-04T15:20:38.000Z","assembly":"drive"},"message":"DRIVE, Joined room john"},"headers":{"Access-Control-Allow-Origin":"","Access-Control-Allow-Credentials":"","Access-Control-Allow-Methods":"","Access-Control-Allow-Headers":"","Access-Control-Expose-Headers":"","access-control-allow-origin":"","access-control-allow-credentials":"","access-control-allow-methods":"","access-control-allow-headers":"","access-control-expose-headers":""},"statusCode":200}] +1ms
hello again
Sails responded with: { mymodel:
{ name: 'john',
id: 1,
createdAt: '2016-11-04T15:20:38.000Z',
updatedAt: '2016-11-04T15:20:38.000Z',
assembly: 'drive' },
message: 'DRIVE, Joined room john' }
with headers: { 'Access-Control-Allow-Origin': '',
'Access-Control-Allow-Credentials': '',
'Access-Control-Allow-Methods': '',
'Access-Control-Allow-Headers': '',
'Access-Control-Expose-Headers': '',
'access-control-allow-origin': '',
'access-control-allow-credentials': '',
'access-control-allow-methods': '',
'access-control-allow-headers': '',
'access-control-expose-headers': '' }
and with status code: 200
note that it is writing packet
注意它正在写包
{
"type":2,
"data":[
"get",
{
"method":"get",
"headers":{},
"data":{},
"url":"/myModel/connect?name=john"
}
],
"options":{
"compress":true
},
"id":0,
"nsp":"/"
}
Trying sideeffect's suggestion
Here the code I am running pastebin
on the Sails side
verbose: Could not fetch session, since connecting socket has no cookie (is this a cross-origin socket?)
Generated a one-time-use cookie:sails.sid=s%3AR-Sm_JeWKoqayZOku-EvxPR_uUpilwVU.3yRUVjmYSpCl%2BeT4sJIOH%2BUTOL3EjWFabDKbswSlkdIand saved it on the socket handshake.
This will start this socket off with an empty session, i.e. (req.session === {})
That "anonymous" section will only last until the socket is disconnected unless you persist the session id in your database,
or by setting the set-cookie response header for an HTTP request that you *know* came from the same user (etc)
Alternatively, just make sure the socket sends a `cookie` header or query param when it initially connects.
on the socket.io python client DEBUG info:
/usr/local/lib/python2.7/dist-packages/requests/packages/urllib3/util/ssl_.py:334: SNIMissingWarning: An HTTPS request has been made, but the SNI (Subject Name Indication) extension to TLS is not available on this platform. This may cause the server to present an incorrect TLS certificate, which can cause validation failures. You can upgrade to a newer version of Python to solve this. For more information, see https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
SNIMissingWarning
/usr/local/lib/python2.7/dist-packages/requests/packages/urllib3/util/ssl_.py:132: InsecurePlatformWarning: A true SSLContext object is not available. This prevents urllib3 from configuring SSL appropriately and may cause certain SSL connections to fail. You can upgrade to a newer version of Python to solve this. For more information, see https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
InsecurePlatformWarning
/usr/local/lib/python2.7/dist-packages/requests/packages/urllib3/connectionpool.py:843: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
InsecureRequestWarning)
DEBUG:root:192.168.178.20:1337/socket.io [transport selected] websocket
DEBUG:root:192.168.178.20:1337/socket.io [heartbeat reset]
DEBUG:root:192.168.178.20:1337/socket.io [socket.io packet sent] 21["get", {"url": "/path/connect", "headers": {}, "data": {"name": "john"}, "method": "get"}]
DEBUG:root:192.168.178.20:1337/socket.io [socket.io packet received] 0
2 个解决方案
#1
3
Seems it needs a time from your part to create a sails.io.js compatiblity python wrapper arround the given Socketio library. So i thought sharing the implementations while reading the source code of the client side library.
看来你需要一点时间来打造一个帆船。js兼容性python包装器围绕给定的Socketio库。所以我想在阅读客户端库的源代码时共享实现。
What sails.io.js
library here does that, it converts the .get
, .post
, .put
functions to a request via socketio client that sends the following data.
sails.io什么。js库就是这样做的,它通过socketio客户端将.get、.post、.put函数转换为请求,并发送以下数据。
initialize the socketio client lib with http://localhost:1337
使用http://localhost:1337初始化socketio客户端库
pass data to emit
function as a dictionary as described below,
将数据作为字典发送,如下所述,
common emit
data structure is
公共发射数据结构是
emit_data = {
'method' : 'get', # get, post, delete depends on requirement
'headers' : {'header_key': 'header_value'}, # for passing headers
'data': {'key': 'value'}, # for sending /search/?q=hello, {'q': 'hello'}
'url': '/hello' #
}
If you need to convert the last nodejs snippet to this client as
如果需要将最后一个nodejs代码片段转换为这个客户端
import requests
from socketIO_client import SocketIO
def server_responded(*body):
print 'response', body
# first we need to get cookie headers for connection
r = requests.get('localhost:1337/__getcookie/')
emit_data = {
'method' : 'get',
'url': '/hello',
'headers': {'Cookie': r.headers['Set-Cookie']},
}
# update emit_data with extra headers if needed
with SocketIO('localhost', 1337) as socketIO:
# note: event parameter is request method, here get for GET
# second parameter is emit_data structured as described above
socketIO.emit(emit_data['method'], emit_data, server_responded)
# adjust with your requirements
socketIO.wait_for_callbacks(seconds=1)
#2
0
I was never able to address my issue, so I worked around it by creating a relay server to forward messages from Sails.io connection to a socket.io connection and vice-versa.
我一直无法解决我的问题,所以我通过创建一个中继服务器来从sail转发消息来解决这个问题。io连接到插座。输入输出连接,反之亦然。
I created a socket.io server in my Python module using Flask SocketIO, then had my relay connect both the python server (socket.io) and the Sails server (Sails.io).
我创建了一个插座。在我的Python模块中使用Flask SocketIO的io服务器,然后让我的中继连接了Python服务器(socket.io)和帆服务器(Sails.io)。
When message received from SailsJS (Sails.io) then emit/forward it to the python server (socket.io).
当从SailsJS (sail. io)接收到消息时,将其发送/转发到python服务器(socket.com .io)。
In my example, the Sails.io client authenticates to Sails first, but I have NOT implemented authentication for the python server.
在我的例子中,风帆。io客户端首先对帆板进行身份验证,但我还没有为python服务器实现身份验证。
// Connects to SailsIO on SailsJS instance
var sailsIO = require('sails.io.js')(require('socket.io-client'));
// Connects to SocketIO server
var socketIO = require('socket.io-client')('https://localhost:7000');
socketIO.on('connect', function() {
console.log("Connect");
});
socketIO.on('disconnect', function() {
console.log("Disconnect");
});
var request = require('request');
var inspect = require('eyespect').inspector({
styles: {
all: 'magenta'
}
});
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; // Ignore the certs
/* Options */
sailsIO.sails.url = 'https://192.168.178.20:1337';
sailsIO.sails.rejectUnauthorized = false;
// ...
/* Authenticate */
var authJson = {
"email": "me@domain.com",
"password": "mypassword"
};
var options = {
method: 'put',
body: authJson,
json: true,
url: 'https://192.168.178.20:1337/login',
headers: {
'Content-Type': 'application/json'
}
}
request(options, function(err, res, body) {
if (err) {
inspect(err, 'error posting json')
return
}
var headers = res.headers
var statusCode = res.statusCode
var cookie = headers['set-cookie'][0].split(';')[0]
inspect(headers, 'headers');
inspect(cookie, "Cookie")
inspect(statusCode, 'statusCode');
inspect(body, 'body');
sailsIO.sails.headers = {
'Cookie': cookie
};
/* Connects to SailsJS */
sailsIO.socket.request({
method: 'get',
url: '/path/to',
data: {
name: 'john'
},
headers: {
'Cookie': cookie
}
}, function(resData, jwres) {
inspect(jwres, "jwres");
if (jwres.error) {
console.log(jwres.statusCode); // => e.g. 403
return;
}
console.log(jwres.statusCode); // => e.g. 200
});
});
sailsIO.socket.on('connecting', function() {
console.log('Connecting to server');
});
sailsIO.socket.on('hello', function(data) {
inspect(JSON.stringify(data), "hello (someone connected)");
});
/**
* On message from Sails, re-emit to python SocketIO server via socket.io client
*/
sailsIO.socket.on('event', function(data) {
inspect(JSON.stringify(data), "Data received");
socketIO.emit('event', data);
});
#1
3
Seems it needs a time from your part to create a sails.io.js compatiblity python wrapper arround the given Socketio library. So i thought sharing the implementations while reading the source code of the client side library.
看来你需要一点时间来打造一个帆船。js兼容性python包装器围绕给定的Socketio库。所以我想在阅读客户端库的源代码时共享实现。
What sails.io.js
library here does that, it converts the .get
, .post
, .put
functions to a request via socketio client that sends the following data.
sails.io什么。js库就是这样做的,它通过socketio客户端将.get、.post、.put函数转换为请求,并发送以下数据。
initialize the socketio client lib with http://localhost:1337
使用http://localhost:1337初始化socketio客户端库
pass data to emit
function as a dictionary as described below,
将数据作为字典发送,如下所述,
common emit
data structure is
公共发射数据结构是
emit_data = {
'method' : 'get', # get, post, delete depends on requirement
'headers' : {'header_key': 'header_value'}, # for passing headers
'data': {'key': 'value'}, # for sending /search/?q=hello, {'q': 'hello'}
'url': '/hello' #
}
If you need to convert the last nodejs snippet to this client as
如果需要将最后一个nodejs代码片段转换为这个客户端
import requests
from socketIO_client import SocketIO
def server_responded(*body):
print 'response', body
# first we need to get cookie headers for connection
r = requests.get('localhost:1337/__getcookie/')
emit_data = {
'method' : 'get',
'url': '/hello',
'headers': {'Cookie': r.headers['Set-Cookie']},
}
# update emit_data with extra headers if needed
with SocketIO('localhost', 1337) as socketIO:
# note: event parameter is request method, here get for GET
# second parameter is emit_data structured as described above
socketIO.emit(emit_data['method'], emit_data, server_responded)
# adjust with your requirements
socketIO.wait_for_callbacks(seconds=1)
#2
0
I was never able to address my issue, so I worked around it by creating a relay server to forward messages from Sails.io connection to a socket.io connection and vice-versa.
我一直无法解决我的问题,所以我通过创建一个中继服务器来从sail转发消息来解决这个问题。io连接到插座。输入输出连接,反之亦然。
I created a socket.io server in my Python module using Flask SocketIO, then had my relay connect both the python server (socket.io) and the Sails server (Sails.io).
我创建了一个插座。在我的Python模块中使用Flask SocketIO的io服务器,然后让我的中继连接了Python服务器(socket.io)和帆服务器(Sails.io)。
When message received from SailsJS (Sails.io) then emit/forward it to the python server (socket.io).
当从SailsJS (sail. io)接收到消息时,将其发送/转发到python服务器(socket.com .io)。
In my example, the Sails.io client authenticates to Sails first, but I have NOT implemented authentication for the python server.
在我的例子中,风帆。io客户端首先对帆板进行身份验证,但我还没有为python服务器实现身份验证。
// Connects to SailsIO on SailsJS instance
var sailsIO = require('sails.io.js')(require('socket.io-client'));
// Connects to SocketIO server
var socketIO = require('socket.io-client')('https://localhost:7000');
socketIO.on('connect', function() {
console.log("Connect");
});
socketIO.on('disconnect', function() {
console.log("Disconnect");
});
var request = require('request');
var inspect = require('eyespect').inspector({
styles: {
all: 'magenta'
}
});
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; // Ignore the certs
/* Options */
sailsIO.sails.url = 'https://192.168.178.20:1337';
sailsIO.sails.rejectUnauthorized = false;
// ...
/* Authenticate */
var authJson = {
"email": "me@domain.com",
"password": "mypassword"
};
var options = {
method: 'put',
body: authJson,
json: true,
url: 'https://192.168.178.20:1337/login',
headers: {
'Content-Type': 'application/json'
}
}
request(options, function(err, res, body) {
if (err) {
inspect(err, 'error posting json')
return
}
var headers = res.headers
var statusCode = res.statusCode
var cookie = headers['set-cookie'][0].split(';')[0]
inspect(headers, 'headers');
inspect(cookie, "Cookie")
inspect(statusCode, 'statusCode');
inspect(body, 'body');
sailsIO.sails.headers = {
'Cookie': cookie
};
/* Connects to SailsJS */
sailsIO.socket.request({
method: 'get',
url: '/path/to',
data: {
name: 'john'
},
headers: {
'Cookie': cookie
}
}, function(resData, jwres) {
inspect(jwres, "jwres");
if (jwres.error) {
console.log(jwres.statusCode); // => e.g. 403
return;
}
console.log(jwres.statusCode); // => e.g. 200
});
});
sailsIO.socket.on('connecting', function() {
console.log('Connecting to server');
});
sailsIO.socket.on('hello', function(data) {
inspect(JSON.stringify(data), "hello (someone connected)");
});
/**
* On message from Sails, re-emit to python SocketIO server via socket.io client
*/
sailsIO.socket.on('event', function(data) {
inspect(JSON.stringify(data), "Data received");
socketIO.emit('event', data);
});