Cannot execute any statement in express route except last - node.js

I have set up an express route, which is expected to serve an HTML file, which is this:
app.use('/',express.static("../first-app/dist"));
var filepath=path.join(__dirname,"..","first-app","dist","index.html");
app.get('/', (req, res) => {
console.log("hello");
console.log("hello");
res.sendFile(filepath);
});
When '/' route is hit, the file is served correctly but none of the statement above res.sendFile is being executed. This is little bit strange because the statements are expected to execute in sequence. No matter what I write above the last line, nothing will execute.
Please help me to find the problem in this.
Thanks in advance.

If the response/file is getting sent, if these are all your routes and if you don't see the output from console.log("hello");, then the only possible answer is that this route:
app.use('/',express.static("../first-app/dist"));
is what is sending the file. From your code, it looks like this will be the case because index.html is inside the ../first-app/dist and if express.static() gets a request for /, then it looks for index.html in the target directory. If it finds it, then it sends it and routing does not continue any further.
So, you have a couple possible solutions.
Move index.html somewhere else so express.static() doesn't find it and then change where you build filepath from to the new location of index.html.
Add an option to express.static("../first-app/dist", {index: false}) to tell it not to look forindex.htmlif the path is/`. You can see that option documented here.
Move the app.get('/', ...) route before the express.static() route so it gets the request first.

Related

How to ignore specific files to be loaded when I use route parameters in Express

When I make a GET request with route parameters in express with mongoose like the following code, I sometimes see that the browser tries to load some unexpected files such as favicon.ico, robots.txt, humans.txt, sitemap.xml, ads.txt, etc., and 404 error shows up in the browser console.
app.get("/:userId", ...);
By refering to this Q&A, I figured out that if I don't use the route parameters right after the root route like the following code, it doesn't happen.
app.get("/user/:userId", ...);
In the same Q&A, however, there seem to be another way that uses req.url to ignore those unexpected files to be loaded, but it isn't explained in detail.
How do you do that?
All that's meant in that other answer is that you could examine req.url in your route handler and make sure it is not a known special name. In this specific case, it's probably simpler to use req.params.userId instead of req.url, but you could also use req.url in the same way.
const specials = new Set(["favicon.ico", "robots.txt", "humans.txt", "sitemap.xml", "ads.txt"]);
app.get("/:userId", (res, res, next) => {
// if it's a special URL, then skip it here
if (specials.has(req.params.userId)) {
next();
return;
}
// process your route here
});
Personally, I wouldn't recommend this solution because it presupposes a perfect knowledge of all possible special filenames. I don't use a top level wildcards ever because they ruin the ability to use your server for anything else.

How to write routing and app.js correctly in Node.js

I'd like to know how to write routing in Node.js
now that in my router
router.get('/',(req,res)=>{
res.render("index");
});
router.get('/quiz',(req,res)=>{
res.render("quiz");
});
now that in my app.js
app.use('/', Router);
app.use('/quiz',Router);
When I trid to change app.js
app.use('/', Router);
This work well.
But I change app.js like following
app.use('/quiz'.Router);
I accessed/,then I getquiz.ejs,my expectation is to getindex.ejs
What happend?
and I'd like to understand the relation in app.jsandrouter
Thanks
so app.use is a middleware so whenever you make a get request the app.js start running by order trying to reach the exact same router or we call it End point , in your case this app.use('/quiz'.Router); the params is not correct as the first arg is the path of the route/Endpoint and there's no secound one which tell which res file should i get , so it will pass it until it reach the second one which is ending with / also that's why it got you to router.get('/quiz',(req,res)=>{ res.render("quiz"); });

Why middleware is getting called even when the mount path specified is not it's own?

I am new to node and express, trying to explore things. I made two middlewares both with their specified mount path, the MIDDLEWARE 2 is getting called even when the request is not for it.
The code written by me:
// middleware 1
app.use('/demo',function(req, res, next){
console.log("MIDDLEWARE 1 CALLED");
next();
});
// middleware 2
app.use('/', function(req, res, next){
console.log("MIDDLEWARE 2 CALLED");
next();
});
app.get('/demo',function(req, res){
console.log("Hello, How are you?");
});
And now in the browser, I type: localhost:8000/demo
In console I am getting this:
MIDDLEWARE 1 CALLED
MIDDLEWARE 2 CALLED
Hello, How are you?
My question is when I specify the path in request as /demo why does the second middleware gets called?However, when I type this: localhost:8000, it works as expected Only middleware 2 is called.
Where am I wrong in the first case?
Thanks in advance for any help you are able to provide.
Express' app.use will apply to every request with a path that starts with your entered path. Meaning app.use('/demo', ...) will apply to every route that starts with /demo, and app.use('/', ...) will apply to every route that starts with /, which obviously is every route.
If you only want to have it on the exact / path, maybe app.all('/', ...) could solve your issue as it only applies to the exact match but still for all HTTP methods.

Function isn't being called in Node Js using REST API

I am writing a code in Node JS, which uses mustache for templating html and REST API as backend.
Here is my code that doesn't work.
function setupRoutes(app) {
const base = app.locals.base;
app.get(`${base}/search.html`,doSearchContent(app));
app.get(`${base}/:name`,doGetContent(app));
}
function doSearchContent(app) {
return async function(req, res) {
console.log("here");
}; };
When I run my program and go to base/search.html. It never calls the doSearchContent method.
Any idea why and how I can fix this?
EDIT: The doGetContent works as expected. It's when I run the search.html it doesn't
The express paths should be started with a leading slash. Please change your routes addition to something like this:
...
app.get(`/${base}/search.html`,doSearchContent(app));
app.get(`/${base}/:name`,doGetContent(app));
...
Express matches the path of http request against the 'path' provided for all routes to decide which routes must be called. Since the http paths always start with a slash, your routes also must specify those to match.
These lines
app.get(`${base}/search.html`,doSearchContent(app));
app.get(`${base}/:name`,doGetContent(app));
are not working as you expect. In Express routes we don't invoke functions directly. Instead, we either pass a name of a callback fucntion to invoke, that receives req and res params, or an anonymous callback. In your case it could be something like this:
app.get(`${base}/search.html`,(req, res) => {
console.log("It's alive!");
doSearchContent(app);
});
app.get(`${base}/:name`, (req, res) => {
doGetContent(app)
});
The express paths should be started with a leading slash.
This is not true
Have you added search.html file or used a template to build the HTML?
Make sure the template is being called and not the html file.
Other than that your code looks fine and it should work

ExpressJS sendFile() cannot send URL GET parameters

I'm new to Node.js and Express.js and its routing. It's all set up correctly and it all works except for the following code.
I tried the following code:
app.get("/game/*", function(req, res) {
res.sendFile(__dirname + "/public/game.html?gameId=" + /\/([^\/]+$)/.exec(req.url)[1]);
});
The goal was to send all requests with /game/{gameId} (where gameId is some number) to /public/game.html?gameId={gameId}.
It correctly gets the requests with /game/, gets the gameId parameter from the URL, and attempts to sendFile() it. However, the sendFile() does not work, saying:
web.1 | Error: ENOENT, stat '/opt/lampp/htdocs/papei/public/game/32'
I've searched this error, and I guess it has to do with a file not being found. The problem is, /public/game.html exists. If I remove the ?gameId... part in the sendFile(), then it works. But I guess the sendFile() is looking for an exact URL, and is not finding it.
Is there any way to send URL GET parameters using ExpressJS?
I think the problem is that sendFile tries to find an exact match (which your query parameters break) as you thought.
You could use express-static to serve the html page, and then redirect to it as needed like so:
app.get("/game/:gameid", function(req, res) {
// Not ideal, as it uses two requests
res.redirect('/game.html?gameId=' + req.params.gameid)
});
Or you could put the html inside a template and render it for the response e.g:
app.get("/game/:gameid", function(req, res) {
// Render the 'game' template and pass in the gameid to the template
res.render('game', {gameid: req.params.gameid})
});
Either way, you don't need to use a catch all route and regex to get query parameters, see req.params or req.query in the express documentation.
Hope this helps.

Resources