Sharing Node App and Connect's port - node.js

Is there any way to get Connect to run on the same port as your node app so you can serve up assets using relative or absolute paths?
Right now I have them running on separate ports, which is a pain:
var app = require('http').createServer(handler).listen(81),
connect = require('connect');
connect.createServer(
connect.static(__dirname + '/assets')
).listen(82);

Let connect create the server for you:
var connect=require('connect'),
app=connect.createServer(handler,
connect.static(__dirname+"/assets"))
.listen(81);
Only other difference is that handler now takes a third parameter, next, which is a function that handler should call if it doesn't want to handle the request itself but rather wants to pass it on to the static handler (or anything else implemented via connect).

Related

Node express: dynamically creating a full body link with all attributes?

In a node-express app, I made a function to generate public links, for in this case I want to show a login-link in a view "http://example.net/login/123/tokenishfoobaarchinsignsignisgn"
function link_to(req, path){
return `${req.protocol}://${req.hostname}/${path}`
}
This works OK in production where port is 80 by default.
Though I'm not finding a method on req where I can fetch ports to see if PORT != 80?
I would like to be able to have this know if I'm accessing via localhost:3001 for instance, to be able to add this to link-function. And/or is there a better way to have this type of link-generator functionality from express?
Thanks
AFAIK port is not available on the req object (the rest of what you need is). Normally you know what port your listening on because you provide it to express via the call to listen(), although it's possible to not provide in which case a random port is assigned.
If you need the port, you can get it from the HTTP Server instance returned from listen():
var express = require('express')
var app = express()
var server = app.listen() # Random port is assigned if not provided as 1st arg.
console.log(server.address().port)

Host a Node.js bot (express and botkit)

I just made a bot in node.js for the Cisco Webex Teams application. My bot uses "express" and "botkit". "Express" requires listening on the port "3000" and "Botkit" listening on the port "8080".
I tried heroku.com but it does not accept two predefined ports and does not save files dynamically (fs.write)
var PUBLIC_URL = "http://a796e3b7.ngrok.io";
var port ='3000';
var ACCESS_TOKEN ='xxx';
var SECRET = "xxx";
var express = require('express');
var app = express();
var Botkit = require('botkit');
var controller = Botkit.webexbot({
log: true,
public_address: PUBLIC_URL,
access_token: ACCESS_TOKEN,
secret: SECRET,
webhook_name: process.env.WEBHOOK_NAME || 'Email2Webex',
});
controller.setupWebserver(8080, function(err, webserver) {
controller.createWebhookEndpoints(webserver, bot, function() {
console.log("Webhooks set up!");
});
});
app.post('/mailgun', upload.any(),function(req, res, next){
res.end('ok');
});
app.listen(port);
Currently I use ngrok to host the bot locally on my computer and I want to be able to host it on a server so I do not have to worry about it. how can I do ?
You can't set the port on Heroku apps. Heroku sets the port you're supposed to use through the PORT environment variable, and you should use it via process.env.PORT. Generally speaking, deployed applications should not run on development ports like 8080 - if it's an HTTP server, it must listen on port 80, for example.
In order to have two apps listening at the same time, I suggest you refactor your code and include both your bot and your app into a single express server that will listen at the port defined by Heroku's PORT environment variable.
Concerning access to the file system, it is borderline possible to use it, but there are high security restrictions, so a code that might run on your machine is likely to break on the server. Generally speaking it's a bad idea to access the file system directly in Heroku, except for read-only actions on deployed files. That is in part because the file system is ephemeral, so dont assume your written files will always be there. Most issues related to the caveats of using the file system can be resolved by using database or file storage features provided by Heroku, though.

How to embed multiple instances of node-red in node app

Node-red documentation here gives info on how to embed a single node-red app inside a nodejs app - http://nodered.org/docs/embedding
We wanted our site's users to have their own node-red's on different ports for some custom programming. Is it possible to embed multiple node-red apps in a nodejs applicaiton?
I tried repeating same steps for embedding by changing settings of each call with different port but only one time it is created. First time, a node-red instance is created based on settings. Next time we call, we get port in use. I assume this has something to do with node require doing caching and all... Any workaround for this issue?
If you're interested I created a fork of the node-red project allowing this feature.
this is how you would initiate it:
var http = require('http');
var express = require("express");
var RED = require("node-red")();
var RED2 = require("node-red")();
// Create an Express app
var app = express();
// Add a simple route for static content served from 'public'
app.use("/",express.static("public"));
// Create a server
var server = http.createServer(app);
// Create the settings object - see default settings.js file for other options
var settings = {
httpAdminRoot:"/red1",
httpNodeRoot: "/api",
userDir:"./hhh",
functionGlobalContext: { } // enables global context
};
// Initialise the runtime with a server and settings
RED.init(server,settings);
console.log(RED2.settings === RED.settings, 888, RED2.settings.userSettings);
// Serve the editor UI from /red
app.use(settings.httpAdminRoot,RED.httpAdmin);
// Serve the http nodes UI from /api
app.use(settings.httpNodeRoot,RED.httpNode);
server.listen(8005);
// Start the runtime
RED.start();
var app2 = express();
app2.use("/",express.static("public"));
var server2 = http.createServer(app2);
var settings2 = {
httpAdminRoot:"/red2",
httpNodeRoot: "/api",
userDir:"./hhhh",
functionGlobalContext: { }
};
RED2.init(server2,settings2);
app2.use(settings2.httpAdminRoot,RED2.httpAdmin);
app2.use(settings2.httpNodeRoot,RED2.httpNode);
RED2.start();
server2.listen(8006);
console.log(RED.settings.httpAdminRoot);
console.log(RED2.settings.httpAdminRoot);
console.log(RED2.settings === RED.settings);
also, works on the same port. but make sure to use different paths is so.
https://github.com/aryeharmon/node-red
No, currently Node-RED has no multi-user capabilities and no way to instantiate multiple instances in one process.
You'll have to run separate instances of the application for each user. Have a look at something like FRED for an example of this. This runs individual instances and proxies them to make the integration look like it's all on the same port/domain

can we define two listening ports in a same server in node.js?

I did coding to access the webcamera of my laptop. Then I separately created another project for chat. They both use different server codes(in node.js). Now I want to merge them together in a single code, But my server side code when merged is showing error. Can any one help me with this? Below is my server side code for the merged project:
var mongo=require('mongodb').MongoClient,
client=require('socket.io').listen(8888).sockets;
var static = require('node-static');
var http = require('http');
var file = new(static.Server)();
var app = http.createServer(function (req, res) {
file.serve(req, res);
}).listen(8888);
Followed by other codes below...
I might be wrong but Node.Js is single threaded, therefore it cannot be done.
The problem with your code is you trying to bind two different applications (socket.io and the http server in your case) to the same port 8888. It is not allowed as you will receive this error:
EADDRINUSE, Address already in use
By calling the listen method twice you actually try to bind two applications to the same port passed as argument.
A solution will be to bind socket.io and the server to different ports.

Can I define Express routes in a child process?

So I run a bunch of a little chatbots written in node, nothing too exciting. However, I recently decided to give them their own little web page to display information in a graphical manner. To do this, I figured I'd just run express.
However, I'm running my bots with a wrapper file that starts each chatbot as a child process. Which makes using express a little tricky. Currently I'm starting the express server in the wrapper.js file like so:
var express = require("express");
var web = express();
web.listen(3001);
And then in the child processes, I'm doing this:
var express = require("express");
var web = express();
web.get("/urlforbot",function (req,res) {
res.send("Working!");
});
However, when I navigate to :3001/urlforbot, I get Cannot GET /urlforbot.
Any idea what I'm doing wrong and how to fix this?
Edit: This is my complete wrapper file: http://snippi.com/s/3vn56m2
Edit 2: This is what I'm doing now. I'm hosting each bot on it's own port, and storing that information in the configs. This is the code I'm using, and it appears to be working:
web.get("/"+cfg.route, function (req,res) { // forward the data
res.redirect('http://url.com:'+cfg.port+"/"+cfg.route);
});
Since your bots run as separate processes (any particular reason?), you have to treat each one as having to implement their own HTTP server with Express:
var express = require("express");
var web = express();
web.get("/urlforbot",function (req,res) {
res.send("Working!");
});
web.listen(UNIQUE_PORT_NUMBER);
Each bot process needs to listen on a unique port number, it can't be shared.
Next, you need to map requests coming in on port 3001 in the 'master' process to the correct child process' Express server.
node-http-proxy has a useful option called a ProxyTable with which to create such a mapping, but it requires the master process to know what the endpoint (/urlforbot in your terms) for each bot is. It also requires that the master knows on which port the bots are listening.
EDIT: alternatively, you can use child_process.fork to fork a new process for each of your bots, and communicate between them and the master process (port numbers and such, or even all the data required to generate the /urlforbot pages) using the comm channel that Node provides, but that still sounds like an overly complex setup.
Wouldn't it be possible to create a Bot class instead? You'd instantiate the class for each bot you want to run, and that instance loads its specific configuration and adds its routes to the Express server. All from the same process.

Resources