Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error when trying to pool socks stream connections #80

Closed
pierrickchabi opened this issue Feb 5, 2014 · 10 comments
Closed

Error when trying to pool socks stream connections #80

pierrickchabi opened this issue Feb 5, 2014 · 10 comments
Assignees
Milestone

Comments

@pierrickchabi
Copy link

I'm trying to pool socks stream connections.

Sample code here:

var mysql2 = require('mysql2');
var SocksConnection = require('socksjs');

var mysql_server_options = {
  host: 'database.ho.st',
  port: 3306
};

var socks_options = {
  host: 'proxy.ho.st',
  port: 1080,
  user: 'proxy_username',
  pass: 'proxy_password'
};

var socksConn = new SocksConnection(mysql_server_options, socks_options);

var mysql_options =  {
  database: 'db_name',
  user: 'db_username',
  password: 'secret',
  stream: socksConn
}

var mysqlConnPool = mysql2.createPool(mysql_options);

mysqlConnPool.getConnection(function (err, connection) {

  if (err) {
    return callback(err);
  }
  // Use the connection
  connection.query('SELECT 1+1 as test1;', function (err, rows, fields) {

  // And done with the connection.
  if (err) throw err;

  console.log('Result: ', rows);

  connection.release();
  socksConn.dispose();
  mysqlConnPool.end();
  });
});

But I'm getting this error log:

09:40:00 web.1  | TypeError: Cannot call method 'execute' of null
09:40:00 web.1  |     at PoolConnection.Connection.handlePacket (/Users/me/project/node_modules/mysql2/lib/connection.js:262:28)
09:40:00 web.1  |     at PacketParser.execute (/Users/me/project/node_modules/mysql2/lib/packet_parser.js:40:21)
09:40:00 web.1  |     at null.<anonymous> (/Users/me/project/node_modules/mysql2/lib/connection.js:82:31)
09:40:00 web.1  |     at EventEmitter.emit (events.js:95:17)
09:40:00 web.1  |     at null.<anonymous> (_stream_readable.js:746:14)
09:40:00 web.1  |     at EventEmitter.emit (events.js:92:17)
09:40:00 web.1  |     at emitDataEvents (_stream_readable.js:771:10)
09:40:00 web.1  |     at Readable.on (_stream_readable.js:692:5)
09:40:00 web.1  |     at PoolConnection.Connection (/Users/me/project/node_modules/mysql2/lib/connection.js:81:17)
09:40:00 web.1  |     at new PoolConnection (/Users/me/project/node_modules/mysql2/lib/pool_connection.js:10:14)
09:40:00 web.1  |     at Pool.getConnection (/Users/me/project/node_modules/mysql2/lib/pool.js:40:18)

Is my code is incorrect? More generally, are pooled custom stream connections normally supported? or is it specific to socks stream (my case)?

Thanks for your help.

@sidorares
Copy link
Owner

Works fine for me, both pool and non-pool connection
I'm ssh'ing to local machine to start socks server: ssh -D 1080 username@localhost creates ssh tunnel with socks interface listening on port 1080

Which version are you using? Can you try master?

@pierrickchabi
Copy link
Author

I'm using version 0.11.3.
Will try master ASAP.

@sidorares
Copy link
Owner

actually, I tried npm version, not master ( did npm init && npm install mysql2 socksjs) Maybe I don't handle socks errors correctly - try to add

socksConn.on('error', function(err) {
  console.log('SOCKS error:', err)
});

@alekbarszczewski
Copy link

I am experiencing same issue. It works with simple code as above, however when I try to do same thing in a REST API endpoint I get same error (it happens for pool.getConnection or pool.query). When I replace pool = mysql2.createPool(...) with pool = mysql2.createConnection(...) it works fine (pool.query method). Please look at my example which reproduces the issue:

mysql2 = require 'mysql2'
SocksConnection = require 'socksjs'
url = require 'url'
restify = require 'restify'

proximoUrl = url.parse 'http://proxy:[email protected]'
dbUrl = url.parse 'mysql://user:pass@myhost/mydb'

mysql_server_options =
    host: dbUrl.host
    port: 3306

socks_options =
    host: proximoUrl.host
    port: 1080
    user: proximoUrl.auth.split(':')[0]
    pass: proximoUrl.auth.split(':')[1]

socksConn = new SocksConnection(mysql_server_options, socks_options);

mysql_options =
    database: dbUrl.path.substr(1)
    user: dbUrl.auth.split(':')[0]
    password: dbUrl.auth.split(':')[1]
    stream: socksConn

pool = mysql2.createPool(mysql_options)
server = restify.createServer()

### This is code fragment that when uncommented it makes it work
pool.getConnection (err, conn) ->
    console.log err # outputs null
    conn.release()
###

server.get '/test', (req, res, next) ->

    pool.getConnection (err, connection) ->
        connection.release()
        res.json {}
        next()

server.listen 3000

Its a simple web server that on endpoint GET /test tries to get connection from the pool. When you try to call this endpoint from the browser (localhost:3000/test) it returns error which is thrown by mysql2 (same error as posted by author of this post - it happens when calling getConnection):

{"code":"InternalError","message":"Cannot call method 'execute' of null"}

If you try to getConnection outside of the server (just uncomment commented block from my code) it always work. Moreover after you make single getConnection call outside of the server (as in commented block) then server endpoint starts to work properly (it does not throw error on getConnection anymore). So workaround is to just call getConnection() + conn.release() at startup.

I have no idea why this is happening but maybe there is some conflict between restify & mysql2?

I am using:
mysql2: 0.13.0
restify: 2.8.3
socksjs: 0.4.5

proxy & db urls are fake so you will need your own for testing...

@sidorares
Copy link
Owner

It looks like pool is not aware of stream option - I'lll look at it, thanks for reporting

@sidorares sidorares reopened this Nov 13, 2014
@alekbarszczewski
Copy link

stream option works properly in pool, but only outside of server endpoint handler. It works inside endpoint handler only when pool.getConnection() had been called (just once) before endpoint handler was called. I know that stream option works properly because I am connecting to database with restricted inbound IP.

@sidorares
Copy link
Owner

the problem is that new mysql connection needs new stream. I think I'll add check "If stream is a function, intrerpret it as 'async stream factory' "

and you'll use it like this:

mysql_options =
    database: dbUrl.path.substr(1)
    user: dbUrl.auth.split(':')[0]
    password: dbUrl.auth.split(':')[1]
    stream: function(cb) {
       cb(null, new SocksConnection(mysql_server_options, socks_options));
    }

@alekbarszczewski
Copy link

Sounds good :)

2014-11-14 1:40 GMT+01:00 Andrey Sidorov [email protected]:

the problem is that new mysql connection needs new stream. I think I'll
add check "If stream is a function, intrerpret it as 'async stream factory'
"

and you'll use it like this:

mysql_options =
database: dbUrl.path.substr(1)
user: dbUrl.auth.split(':')[0]
password: dbUrl.auth.split(':')[1]
stream: function(cb) {
cb(null, new SocksConnection(mysql_server_options, socks_options));
}


Reply to this email directly or view it on GitHub
#80 (comment)
.

@alekbarszczewski
Copy link

Any update on this?

@sidorares
Copy link
Owner

Hi! I looked it initially and was afraid that it's to big change to allow connection to be created asynchronously, but now I think that it can be sync function similar to net.createConnection(). If you really need to process something async before you get your connection you can always return simple through stream initially and later pipe your connection to it when it's available

so your code is going to be

mysql_options =
    database: dbUrl.path.substr(1)
    user: dbUrl.auth.split(':')[0]
    password: dbUrl.auth.split(':')[1]
    stream: function() {
       return new SocksConnection(mysql_server_options, socks_options);
    }

I'll try to add this today

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants