0

I have an Django app deployed on Heroku, but due to some requirement I had to create a basic nodejs file and I wish to run it on the same dyno. I googled for solutions but couldnt come up with much apart from the blogs, which all are same https://blog.heroku.com/heroku-django-node So, I did install buildpack mentioned, and my profiles are: Procfile:

web: bin/runsvdir-dyno

Profile.web

django: gunicorn exampledjangoapp.wsgi:application --bind 127.0.0.1:$DJANGO_PORT
node: node node_app/app.js

I have created NODE_ENV and DJANGO_PORT configs in Heroku too. Here is what I see in logs:

 Error: listen EADDRINUSE :::56842
2017-05-05T21:02:15.241005+00:00 app[web.1]:     at Object.exports._errnoException (util.js:1022:11)
2017-05-05T21:02:15.241006+00:00 app[web.1]:     at exports._exceptionWithHostPort (util.js:1045:20)
2017-05-05T21:02:15.241007+00:00 app[web.1]:     at Server._listen2 (net.js:1259:14)
2017-05-05T21:02:15.241007+00:00 app[web.1]:     at listen (net.js:1295:10)
2017-05-05T21:02:15.241008+00:00 app[web.1]:     at Server.listen (net.js:1391:5)
2017-05-05T21:02:15.241009+00:00 app[web.1]:     at Object.<anonymous> (/app/node_app/app.js:15:4)
2017-05-05T21:02:15.241009+00:00 app[web.1]:     at Module._compile (module.js:570:32)
2017-05-05T21:02:15.241010+00:00 app[web.1]:     at Object.Module._extensions..js (module.js:579:10)
2017-05-05T21:02:15.241011+00:00 app[web.1]:     at Module.load (module.js:487:32)
2017-05-05T21:02:15.241011+00:00 app[web.1]:     at tryModuleLoad (module.js:446:12)
2017-05-05T21:02:15.285970+00:00 app[web.1]: buildpack=runit ps=node at=exit status=1 waitpid_lsb=0
2017-05-05T21:02:15.305915+00:00 app[web.1]: buildpack=runit ps=node at=start
2017-05-05T21:02:16.126572+00:00 app[web.1]: events.js:160
2017-05-05T21:02:16.126582+00:00 app[web.1]:       throw er; // Unhandled 'error' event
2017-05-05T21:02:16.126583+00:00 app[web.1]:       ^
2017-05-05T21:02:16.126584+00:00 app[web.1]: 
2017-05-05T21:02:16.126584+00:00 app[web.1]: Error: listen EADDRINUSE :::56842
2017-05-05T21:02:16.126585+00:00 app[web.1]:     at Object.exports._errnoException (util.js:1022:11)
2017-05-05T21:02:16.126586+00:00 app[web.1]:     at exports._exceptionWithHostPort (util.js:1045:20)
2017-05-05T21:02:16.126587+00:00 app[web.1]:     at Server._listen2 (net.js:1259:14)
2017-05-05T21:02:16.126587+00:00 app[web.1]:     at listen (net.js:1295:10)
2017-05-05T21:02:16.126588+00:00 app[web.1]:     at Server.listen (net.js:1391:5)
2017-05-05T21:02:16.126589+00:00 app[web.1]:     at Object.<anonymous> (/app/node_app/app.js:15:4)
2017-05-05T21:02:16.126589+00:00 app[web.1]:     at Module._compile (module.js:570:32)
2017-05-05T21:02:16.126590+00:00 app[web.1]:     at Object.Module._extensions..js (module.js:579:10)
2017-05-05T21:02:16.126591+00:00 app[web.1]:     at Module.load (module.js:487:32)
2017-05-05T21:02:16.126591+00:00 app[web.1]:     at tryModuleLoad (module.js:446:12)
2017-05-05T21:02:16.154176+00:00 app[web.1]: buildpack=runit ps=node at=exit status=1 waitpid_lsb=0
2017-05-05T21:02:16.287874+00:00 heroku[web.1]: Process exited with status 111
2017-05-05T21:02:16.301460+00:00 heroku[web.1]: State changed from starting to crashed

My app.js is:

var http = require('http'),
    httpProxy = require('http-proxy');
//
// Create your proxy server and set the target in the options.
//
httpProxy.createProxyServer({target:'https://example.herokuapp.com/channel'}).listen(process.env.PORT); // See (†)

//
// Create your target server
//
http.createServer(function (req, res) {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.write('request successfully proxied!' + '\n' + JSON.stringify(req.headers, true, 2));
  res.end();
}).listen(process.env.PORT);

So, What I basically trying to do is, on http://example.herokuapp.com to be Django app, and http://example.herokuapp.com/channel to point to nodejs app. Any suggestions please?

Maverick
  • 2,738
  • 24
  • 91
  • 157
  • This is confusing, are both node and django listening on port 80/443? It seems like you know you need to proxy from django to node or node to django but the `Error: listen EADDRINUSE :::56842` makes it look like that is not the case. – Rob Osborne May 09 '17 at 20:05
  • @RobOsborne No, they are set to run on different ports, I have set DJANGO_PORT and NODE_ENV port env variables on Heroku, and set it to run on different ports. Proxy for node is where I am having trouble with I guess. I am really clueless as to how to do it. – Maverick May 10 '17 at 06:56

2 Answers2

1

The Error: listen EADDRINUSE error comes from calling .listen() twice with the same port in app.js.

You are on the right track. Here is an example of how to proxy /channel requests to a Node.JS app and all other requests to another app (a Django app in this case):

var http = require('http'),
    httpProxy = require('http-proxy');

var NODE_PORT = 4711;

var proxy = httpProxy.createProxyServer({});

http.createServer(function(req, res) {
    // For all URLs beginning with /channel proxy to the Node.JS app, for all other URLs proxy to the Django app running on DJANGO_PORT
    if(req.url.indexOf('/channel') === 0) {
        // Depending on your application structure you can proxy to a node application running on another port, or serve content directly here
        proxy.web(req, res, { target: 'http://localhost:' + NODE_PORT });

        // Proxy WebSocket requests if needed
        proxy.on('upgrade', function(req, socket, head) {
            proxy.ws(req, socket, head, { target: 'ws://localhost:' + NODE_PORT });
        });
    } else {
        proxy.web(req, res, { target: 'http://localhost:' + process.env.DJANGO_PORT });
    }
}).listen(process.env.PORT);

// Example node application running on another port
http.createServer(function(req, res) {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.write('Request successfully proxied to Node.JS app');
    res.end();
}).listen(NODE_PORT);
Aule
  • 650
  • 5
  • 13
0

UPDATE: The solution in the link https://blog.heroku.com/heroku-django-node must be corrected.

Replace 127.0.0.0 with 0.0.0.0 in

django: gunicorn path.to.wsgi:application --bind 127.0.0.1:$DJANGO_PORT

For some reasons Heroku has issues with 127.0.0.1 or localhost. See also https://help.heroku.com/P1AVPANS/why-is-my-node-js-app-crashing-with-an-r10-error

While working on this setup be sure to have in Procfile.web both the lines

django: gunicorn path.to.wsgi:application --bind 127.0.0.1:$DJANGO_PORT
node: node server.js

because you are binding on $DJANGO_PORT, but it's mandatory to bind something also on the default $PORT (here, the node server) as explained in https://devcenter.heroku.com/articles/dynos#web-dynos otherwise you get the error

Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch