Express Does app.js get ran on every request? - javascript

I am building an express server with pretty standard stuff. I've been unable to get express.router() to execute my routes correctly, which has caused me to dig deeper into what is actually happening when a page is requested from a server running an express app.
console.log('App.JS has ran!');
var http = require('http');
var express = require('express');
var app = express();
var server = http.createServer(app);
var mongoose = require('mongoose');
mongoose.connect('mongodb://52.27.161.16');
mongoose.connection.on("connect",function(err) {
if (err) throw err;
console.log('hello found!');
});
var bodyParser = require('body-parser');
app.use(bodyParser.json());
var router = express.Router();
router.get('/hi'), function (req, res) {
res.send('/hi route response');
};
router.get('/', function(req, res) {
res.send('default route reached');
});
app.use('*', router);
server.listen(config.server.listenPort);
Pretty standard stuff—but for some reason whenever I navigate to localhost:port/hi I am only getting the res from the / path, i.e. router.get('/', function{} (res.send('default route reached'));
So I've become more interested in what's happening behind the scenes. I've noticed that the server only logs to the terminal the output not related to the bodyParser on the first request. I.e., the console.log at the top of the file only gets ran when the application is started, and never after, though bodyParser correctly logs requests for each request instance.
What's going on exactly when a request is made to the server? Is the app object and route cached and being served? Why is app.js not being re-evaluated on each request? Is only the router object responsible for sending requests over?
It would be helpful to know this, to figure out why my router is not responding with the correct route.
Thanks a bunch!

The app object is the express application that you are creating. It is basically a wrapper for the express module which includes all the express functionalities. It basically reduces the code that you requires to handle requests made to the server, rendering the HTML views, registering a template engine etc. This app object is passed to the server object that you are creating and the server continuously listens to requests in the port that you have configured. So, when the server is running, the app object is initiated only once and the requests to the server are handled by the node event loop.

Related

Restart NodeJS app automatically after app crashes

I want to add code to my NodeJS (Express) app so that it will restart automatically after crashes with some error. I know about forever npm package, but I found only examples with running app in development, while my goal is to use it in production (app is already on production server). Should I add some code inside app.js (main file for my application) or in different files?
Here's my app.js code:
const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const path = require("path");
const con = require("./databaseConnection");
const app = express();
/* Middleware */
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
/* Redirect http to https */
app.enable('trust proxy');
app.use (function (req, res, next) {
if (req.secure) {
// request was via https, so do no special handling
next();
} else {
// request was via http, so redirect to https
res.redirect('https://' + req.headers.host + req.url);
}
});
/* Routers */
const authRouter = require("./routers/authRouter");
const userRouter = require("./routers/userRouter");
app.use("/auth", authRouter);
app.use("/user", userRouter);
app.listen(5000);
I think the program you are looking for is pm2. https://pm2.keymetrics.io/docs/usage/quick-start/
You could listen for any unhandled exceptions/errors and handle them to stop the server crashing because of an uncaught error, but there are a bunch more problems that could happen with the process itself that would go unhandled such as memory leaks, which is why you need to use a process manager rather than something internal inside your express server.
It's better to use the pm2 daemon to manage the server processes for you, it also comes with a built-in dashboard, logging, and useful restarting configuration options such as
Restart app at a specified CRON time
Restart app when files have changed
Restart when app reach a memory threshold
Delay a start and automatic restart
Disable auto restart (app are always restarted with PM2) when crashing or exiting by default)
Restart application automatically at a specific exponential increasing time

Is Express.js platform-independent?

I'm just starting out with Express.js. In the official getting started guide, they showed the following basic code:
var express = require('express')
var app = express()
// respond with "hello world" when a GET request is made to the homepage
app.get('/', function (req, res) {
res.send('hello world')
})
The first parameter to app.get() is a forward-slash indicating the root directory. But the slash is a backward-slash in windows systems. Does express deal with these differences automatically, or do we need to write extra code for it? When I was using the http module, I did have to consider and correct for these differences. Thanks for the help!
app.get('/', ...) declares a handler for when an HTTP GET request is made to the URL path /. E.g. http://localhost:8080/. It has nothing to do with file paths on the server’s file system. If you use any functions that do take a file path, you may have to account for the differences between Windows and *NIX, that depends on the function.

Node.js client can't see data from Express server

I am setting up a Client/Server communication between my tablet and my PC. My Client cant get any data from the server, what am I doing wrong.
My PC is running a Node.js server (using Express) and my tablet runs a client written in Node.js (using Express). I can access the server via the browser and get the data, but not through the javascript code.
My SERVER code is:
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('App requested a connection');
});
app.listen(3000, () => console.log('Listening on port 3000!'));
app.get("/boxes", function (req, res)
{
//res.send(req.params[0]);
res.send("All boxes are in the basement");
});
My CLIENT code is:
const express = require('express');
const app = express();
console.log("Client working ...");
app.get("http://127.0.0.1:3000/boxes", function (req, res)
{
console.log("inside...");
console.log(res);
});
The CLIENT should return "All boxes are in the basement" and I get this when I use a browser but it doesn't work if I run the client code. The only message I get from client is "Client working ...".
Does anybody know what I am doing wrong?
Cheers
Express is a library for setting up and configuring an http server for incoming requests. It does not make outgoing requests to other servers. So, your client code is not a client at all.
Several problems here:
127.0.0.1 refers to your local device so your client is referring to itself when it uses 127.0.0.1.
In your client app.get("http://127.0.0.1:3000/boxes") is not a request for data. That attempts to set up an Express route for incoming requests as if you were declaring a second server. But, it's not even done correctly because you would only use the path there.
For a client to make a request of some other server, you would need to use a library call that actually does http requests. For example, you could do something like this:
Code:
const rp = require('request-promise');
rp.get("http://ipaddressOfServer:3000/boxes").then(data => {
// have response here
}).catch(err => {
// error here
});
I chose to use the request-promise library, but there are multiple different ways to make an http request. You can also use http.get() (lower level), request() (from the request library) or axios() from the axios library, etc...
Note, the computer your server is on (assuming it's running a desktop OS) will also have to probably turn of it's local firewall (e.g. windows firewall) or set up a specific rule to allow incoming connections on port 3000. Without that, the incoming connection will be blocked (for security reasons).

Okay to add a route to Node.js Express while listening?

Obviously the typical example of adding routes to express follows something like the following:
var express = require('express');
var app = express();
app.get('/', function(req, res){
res.send('hello world');
});
app.listen(3000);
Clearly, in most cases you know the get route exists before the server begins listening. But what if you want to dynamically create new routes once the server is listening? In other words, I want to do something like the following:
var express = require('express');
var app = express();
app.listen(3000, function () {
app.get('/', function(req, res){
res.send('hello world');
});
});
In practice the callback of the route would obviously be pulled dynamically from some remote source. I've tested the above code and everything appears to function properly, however, I was hoping to get confirmation that there wouldn't be any unintended side-effects of creating routes after app.listen is called before I move forward with this pattern.
Note: To clarify, I don't know what the routes will be when I write the main server.js file that will be creating the express server (hence why I can't create the routes before listen is called). The list of routes (and their respective handlers/callback functions) will be pulled from a database while the server is starting up/running.
According to TJ (author of Express), it’s okay to add routes at runtime.
The main gotcha is going to be that routes are evaluated in the order they were added, so routes added at runtime will have a lower precedence than routes added earlier. This may or may not matter, depending on your API design.

node.js /socket.io/socket.io.js not found

i keep on getting the error
/socket.io/socket.io.js 404 (Not Found)
Uncaught ReferenceError: io is not defined
my code is
var express = require('express'), http = require('http');
var app = express();
var server = http.createServer(app);
var io = require('socket.io').listen(server);
server.listen(3000);
and
<script src="/socket.io/socket.io.js"></script>
what is the problem ???
any help is welcome!
Copying socket.io.js to a public folder (something as resources/js/socket.io.js) is not the proper way to do it.
If Socket.io server listens properly to your HTTP server, it will automatically serve the client file to via http://localhost:<port>/socket.io/socket.io.js, you don't need to find it or copy in a publicly accessible folder as resources/js/socket.io.js & serve it manually.
Code sample Express 3.x -
Express 3 requires that you instantiate a http.Server to attach socket.io to first
var express = require('express')
, http = require('http');
//make sure you keep this order
var app = express();
var server = http.createServer(app);
var io = require('socket.io').listen(server);
//...
server.listen(8000);
Happy Coding :)
How to find socket.io.js for client side
install socket.io
npm install socket.io
find socket.io client
find ./ | grep client | grep socket.io.js
result:
./node_modules/socket.io/node_modules/socket.io-client/dist/socket.io.js
copy socket.io.js to your resources:
cp ./node_modules/socket.io/node_modules/socket.io-client/dist/socket.io.js /home/proyects/example/resources/js/
in your html:
<script type="text/javascript" src="resources/js/socket.io.js"></script>
It seems that this question may have never been answered (although it may be too late for the OP, I'll answer it for anyone who comes across it in the future and needs to solve the problem).
Instead of doing npm install socket.io you have to do npm install socket.io --save so the socket.io module gets installed in your web development folder (run this command at the base location/where your index.html or index.php is). This installs socket.io to the area in which the command is run, not globally, and, in addition, it automatically corrects/updates your package.json file so node.js knows that it is there.
Then change your source path from '/socket.io/socket.io.js' to 'http://' + location.hostname + ':3000/socket.io/socket.io.js'.
... "You might be wondering where the /socket.io/socket.io.js file
comes from, since we neither add it and nor does it exist on the filesystem. This is
part of the magic done by io.listen on the server. It creates a handler on the server
to serve the socket.io.js script file."
from the book Socket.IO Real-time Web
Application Development, page 56
You must just follow https://socket.io/get-started/chat/ and all will work.
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
http.listen(3000, function(){
console.log('listening on *:3000');
});
If you are following the socket.io tutorial https://socket.io/get-started/chat/, you should add this line as below.
app.use(express.static(path.join(__dirname, '/')))
This is because in the tutorial, Express will only catch the url
/ and send the file of index.html.
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html')
})
However, in the index.html, you have a script tag (<script src="/socket.io/socket.io.js"></script>) requests the resouce of socket.io-client, which is not routed in index.js (it can be found in console-network that the url is http://localhost:3000/socket.io/socket.io.js).
Please check the directory path mentioned in your code.By default it is res.sendFile(__dirname + '/index.html');
make sure you index.html in proper directory
Steps to debug
npm install socket.io --save in static files (index.html) for example, you may have installed it globally and when you look at the debugger, the file path is empty.
Change your script file and instantiate the socket explicitly adding your localhost that you have set up in your server file
<script src="http://localhost:5000/socket.io/socket.io.js"></script>
<script>
const socket = io.connect("localhost:5000");
$(() =>
Double check that the data is flowing by opening a new browser tab and pasting http://localhost:5000/socket.io/socket.io.js you should see the socket.io.js data
Double check that your server has been set-up correctly and if you get a CORs error npm install cors then add it to the server.js (or index.js whatever you have chosen to name your server file)
const cors = require("cors");
const http = require("http").Server(app);
const io = require("socket.io")(http);
Then use the Express middleware app.use() method to instantiate cors. Place the middleware this above your connection to your static root file
app.use(cors());
app.use(express.static(__dirname));
As a final check make sure your server is connected with the http.listen() method where you are assigning your port, the first arg is your port number, for example I have used 5000 here.
const server = http.listen(5000, () => {
console.log("your-app listening on port", server.address().port);
});
As your io.on() method is working, and your sockets data is connected client-side, add your io.emit() method with the callback logic you need and in the front-end JavaScript files use the socket.on() method again with the call back logic you require. Check that the data is flowing.
I have also edited a comment above as it was the most useful to me - but I had some additional steps to take to make the client-server connection work.
If you want to manually download "socket.io/socket.io.js" file and attaché to html (and not want to get from server runtime) you can use https://cdnjs.com/libraries/socket.io
like
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.min.js" integrity="sha512-eVL5Lb9al9FzgR63gDs1MxcDS2wFu3loYAgjIH0+Hg38tCS8Ag62dwKyH+wzDb+QauDpEZjXbMn11blw8cbTJQ==" crossorigin="anonymous"></script>
while this doesn't have anything to do with the OP, if you're running across this issue while maintaining someone else's code, you might find that the problem is caused by the coder setting io.set('resource', '/api/socket.io'); in the application script, in which case your HTML code would be <script>type="text/javascript" src="/api/socket.io/socket.io.js"></script>.
If this comes during development. Then one of the reasons could be you are running a client-side file(index.html). But what you should do is run your server(example at localhost:3000) and let the server handle that static file(index.html). In this way, the socket.io package will automatically make
<script src="/socket.io/socket.io.js"></script> available on the client side.
Illustration(FileName: index.js):
const path = require('path');
const express = require('express');
const socketio = require('socket.io');
const port = 3001 || process.env.PORT;
const app = express();
const server = http.createServer(app);
const io = socketio(server);
//MiddleWares
app.use(express.json());
app.use(
express.urlencoded({
extended: false,
})
);
app.use(express.static(__dirname + '/public'));
app.get('/', (req, res) => {
res.sendFile('index.html');
});
io.on('connect', (socket) => {
console.log('New user joined');
}
server.listen(port, () => {
console.log(`App has been started at port ${port}`);
});
After this run your server file by the command
node index.js
Then open the localhost:${port}, Replace port with given in the index.js file and run it.
It solved my problem. Hope it solves yours too.

Categories