Problem Statement: On running a Node.js application URL on the web browser it throws the following error:
Cannot GET/
Example: Let’s create a simple Node.js application that throws the same error.
Step 1: Initializes NPM: Create and Locate your project folder in the terminal & type the command
npm init -y
It initializes our node application & makes a package.json file.
Step 2: Install Dependencies: Locate your root project directory into the terminal and type the command
npm install express
To install Express as dependencies inside your project
Step 3: Create Server File: Create an ‘app.js’ file, inside this file require an express Module, and create a constant ‘app’ for creating an instance of the express module.
const express = require('express') const app = express()
Step 4: Create a Message Route: Create a get route using app.get() method which sends “hello” as a text to the web browser.
app.get("/messages", (req, res) => { res.send("Hello"); });
Step 5: Set up a port to run our server: We will do it by using the express, app.listen() method.
app.listen(3000, () => { console.log("listening on http://localhost:3000"); })
Complete Code:
Javascript
const express = require(
'express'
)
const app = express()
app.get(
"/messages"
, (req, res) => {
res.send(
"Hello"
);
});
app.listen(3000, () => {
})
Output:
Reason: Since in the server file, we create a get route for ‘/messages’ URL but inside the browser, we try to get the ‘/’ URL which is not specified in our server file that’s why it throws the error.
Solution Approach: We have to set up a universal route, and when any route or URL which are not specified inside the server file will call then the universal URL sends a “404 URL NOT FOUND” message.
app.get("/:universalURL", (req, res) => { res.send("404 URL NOT FOUND"); });
Complete Code:
Javascript
const express = require(
'express'
)
const app = express()
app.get(
"/messages"
, (req, res) => {
res.send(
"Hello"
);
});
app.get(
"/:universalURL"
, (req, res) => {
res.send(
"404 URL NOT FOUND"
);
});
app.listen(3000, () => {
})
Output:
Introduction
This article has a specific content on solving an error message. The detail of the error message exist in the title of this article. It is an error message of ‘Cannot Get /’ exist in the page of NodeJS application. Actually, the error appear upon executing a NodeJS application. Running the application by executing a command in the command line interface as follows :
[admin@10 nodejs]$ node app.js Test NodeJS !
But upon accessing the page via web browser, the following is the image of the page after successfully executing the NodeJS application :
Actually, the code has a part for listening to a specific port. In the context of this article, the application is listening to port 3001. The following is the actual content of the source code with the file name of ‘app.js’ :
const express = require("express"); const app = express(); app.get("/"); app.listen(3001); console.debug("Test NodeJS !");
So, while printing the ‘Test NodeJS !’ in the command line interface, it also listens for incoming request in port 3001. But apparently, accessing port 3001 via web browser fail with the error message as in the above image.
Solving the problem
In order to solve the problem, just fix the above line of code especially in the following line :
app.get("/");
Upon executing a GET request by typing the address of ‘localhost:3001’ in the web browser’s address bar, the above image appear. The error message is ‘Cannot Get /’. It is because there is no definition for responding the value from the line of ‘app.get(‘/’)’. In order to a page retrieving a responding value, just define it in the line of the code. The following is one of the method for defining at responding value to the GET request as follows :
app.get("/",(req,res) => res.send("Response from the GET request"));
Another form of definition with the full-length syntax of the function exist as follows :
app.get("/", function (req,res) { res.send("Response from the GET request") });
So, the full content of the file with the name of ‘app.js’ exist as follows :
const express = require("express"); const app = express(); app.get("/",(req,res) => res.send("Response from the GET request")); app.listen(3001); console.debug("Test NodeJS !");
Or another form of the function definition displaying the full content of the file :
const express = require("express"); const app = express(); app.get("/", function (req,res) { res.send("Response from the GET request") });app.listen(3001); console.debug("Test NodeJS !");
So this might not be an issue with express’ internal workings, as I did post this up on stackoverflow initially thinking that this issue was purely arising from how I am approaching using express, but after experimenting with multiple setups I’m not so sure what’s what. Currently I have a setup for hot reloading as follows:
// server.js
const app = express();
app.use(function (req, res, next) {
require('./server/index')(req, res, next);
require('./server/foo')(req, res, next); // another url page
});
Each require file inside app.use follows the following example template:
const router = express.Router();
router.get('whatever endpoint' you want, (req, res) => {
console.log('whatever endpoint you want');
res.send('whatever message you want');
});
module.exports = router;
My understanding is that app.use with just a callback will apply to every possible route. And if a user navigates to a route that doesn’t exist, say ‘/bar’ for example, express’ cannot GET/ should be displayed at whatever the incorrect endpoint was.
What actually happens however, is that express crashes with the ERR_HTTP_HEADERS_SENT error. So of course that’s bad, so to get around that, I would just apply my own catch-all inside the above app.use at the end of the function as follows:
//server.js
app.use(function (req, res, next) {
require('./server/index')(req, res, next);
require('./server/foo')(req, res, next);
require('./server/catch-all')(req, res, next);
});
//catch-all.js
router.get('*', (req, res) => {
console.log('catch all');
if(!res.headersSent){ // this is necessary to prevent the ERR_HTTP_HEADERS_SENT error
res.redirect('/');
}
})
This fixes all of the issues, but I’ve noticed that the catch-all console.log is always called twice; once for when the rest of the require statements have been called and it has not found a match, hence using the catch-all endpoint. The second is for when the redirect to the main page happens.
If my understanding is correct, since app.use() is being called for every single request, this causes the double call effect when invoked by the redirect handler? If so, if we omit the catch-all, and go back to what was originally done at the top of this post, why does express crash with the ERR_HTTP_HEADERS_SENT error? Is it again because of the app.use being called for every route, including routes that aren’t defined and being handled by cannot GET?
If this is the case, and this is the crux of what I’m trying to get at, shouldn’t express internally recognise that the cannot get / error handler has already been called? It seems like it’s attempting to send two responses that both say cannot GET whatever page the error is on, hence the ERR_HTTP_HEADERS_SENT error.
The alternative is splitting the above into two separate app.use calls, that only handle specific routes:
app.use('/', require('./server/index'));
app.use('/foo', require('./server/foo'));
However, if you have numerous routes, having loads of app.use calls littering your code becomes repetitive, and your docs state both options as being valid. Is it just a case of it needing to be done this way by design or am I perhaps missing another possible option?