Why is `app.get('*')` always triggered? - javascript

Consider this little app:
var express = require("express");
var app = express();
app.get("/json", function(req, res){
console.log("JSON route");
res.json({foo: "bar"});
});
app.get("/", function(req, res){
console.log("Slash route");
res.send("Hello");
});
app.get("*", function(req, res){
console.log("Star route");
res.redirect("/");
});
app.listen(3000, function(){
console.log("Listening.");
});
Whenever I go to either localhost:3000 or localhost:3000/json in my browser, I can see from my server log that the star * route is also triggered. This is still true if it is changed to app.get("/*")
Why is this? I thought res.send and res.json halted execution.

When you request something with your browser, it will automagically try to request a favicon. Since your server doesn't have a route defined for a favicon, it goes to the * route, causing this confusion.

Related

Node.js Express return 404 if file not found in only Assets folder

I am trying to create an SPA using Express with following code
var express = require('express');
const path = require('path');
var app = express();
app.use('/assets', express.static(path.resolve(__dirname, 'www', 'assets')));
app.get('/*', (req, res)=>{
res.sendFile(path.resolve('www', 'index.html'));
});
var server = app.listen(3000, function(){});
This code works good but the problem is this responds with my index.html even when a file is not found in my assets folder. I want it to respond with error of 404 Not Found if some url is not present in assets folder
I tried using this code after line app.use('/assets'...
app.use(function (req, res, next) {
res.status(404).send("404 Not Found");
});
but not working
Issue is with
app.get('/*', (req, res)=>{
res.sendFile(path.resolve('www', 'index.html'));
});
Instead, use
app.get('/', (req, res)=>{
res.sendFile(path.resolve('www', 'index.html'));
});
So, I finally got the way to solve it
app.get('/*', (req, res)=>{
if(req.path.includes('/assets'))
{
fs.access(req.path, (err) => {
if(err)
{
res.status(404).send("Sorry can't find that!");
return;
}
});
}
res.sendFile(path.resolve('www', 'index.html'));
});
In the code, I have told to check if the request is about a file located in assets folder then check if the file exists, if does not exists then send 404 error with message and just return, otherwise do nothing but return the file.

Refreshing the page using Node.js / Express?

I need to refresh the page in my small Node and Express app as soon as the user connects. I have tried res.redirect('index.html') in the second snippet, but it throws an error when I try to connect to the root URL.
The following code is run when the user connects to the root URL:
app.get('/', (req, res) => {
res.redirect('/index.html')
app.use(express.static(path.join(__dirname, 'public')))
});
and I detect when the user connects with:
io.on('connection', (socket) => {}
Thanks in advance!
app.get('/', (req, res) => {
// res.redirect('back');
// OR
res.redirect(req.get('referer'));
app.use(express.static(path.join(__dirname, 'public')))
});

why slash URL runs with all of other URLs in the middleware of NodeJS?

Why I enter http://localhost:3000/product on the browser, the output will be both outputs of '/' and '/product'?
Please look at this snippet code.
const express = require('express');
const app = express();
// http://localhost:3000/product
app.use('/product', (req, res, next)=>{
console.log('In product page');
res.send('<h1>Product Page</h1>');
});
// http://localhost:3000/
app.use('/', (req, res, next)=>{
console.log('In main page');
res.send('<h1>Main Page</h1>');
});
app.listen(3000);
This image is my app's output.
It could have multiple reasons. One that I think of right now is that the browser requests http://localhost:3000/favicon.ico automatically after product.html, which triggers the use('/', ...) route.
Maybe you should use app.all(...) instead of app.use(...), to avoid this "wildcard" on every path that should rather be a 404 page.
The app.use() method is used to bind application level middleware. Not for accepting GET request as you are expecting.
You should use
// http://localhost:3000/product
app.get('/product', (req, res)=>{
console.log('In product page');
res.send('<h1>Product Page</h1>');
});
// http://localhost:3000/
app.get('/', (req, res)=>{
console.log('In main page');
res.send('<h1>Main Page</h1>');
});
Because in express whatever you define with app.use() is middleware and it always executes until and unless it has some path defined
app.use('/', (req, res, next)=>{
console.log('In main page');
res.send('<h1>Main Page</h1>');
});
above will always execute because it contains root path and every url has root path
Check this link for further info https://expressjs.com/en/4x/api.html#app.use
You should define your routing with express router using app.get("/") or app.post("/") and it will help for more info https://expressjs.com/en/guide/routing.html

React + Express.js server should always return the same index.html file, no matter what url route

I've been trying to get this fixed for the last few hours but can't find something that works. What I'm using right now is the standard:
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html');
});
I've tried to use the solution someone posted in another thread:
app.get(/*./, function (req, res) {
res.sendFile(__dirname + '/index.html');
});
But this doesn't work and gives me a "Uncaught SyntaxError: Unexpected token <".
I guess that solution is based of expressjs own examples:
app.get(/*test$./, function (req, res) {
res.sendFile(__dirname + '/index.html');
});
Which works for every route that has the phrase "test" in the first level (and ONLY the first lvl '/test'=yes, '/app/test'=no.
WHAT I WANT: Since I've a react app that always returns the same html page and that handles invalid routes within the app I want to make every request to my webpage return the exact same index.html (no matter what route the user asks for, '/' --> index.html '/test/test/test/test' --> index.html and so on.
Anyone have any ideas how I can do this? I've run out of google results
Thanks in advance!
Below is my entire server as of right now:
var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
app.use('/build', express.static('build'));
io.on('connection', function(socket){
console.log('Connected');
});
http.listen(3000, function(){
console.log('listening on *:3000');
});
If you just have app.use(yourStaticMiddleware), the function
"yourStaticMiddleware" will be executed for every request. If that middleware ends the response (eg by calling res.send() or res.sendFile()), then nothing after it will be called except error handlers.
this will work for every get request
app.get("*",function(req,res,next){
res.sendFile(__dirname + '/index.html');
})
Use app.all() method.
This method is used for loading middleware functions at a path for all request methods.
app.all(function (req, res, next) {
//will hit every page request regardless of http method
next(); // pass control to the next handler
});
For more you can refer exprress routing

I can't successfully chain my route handlers?

I've got a node.js/express app I'm working on and routes that look like-
app.post('/user/:who/update', isLoggedIn, userUpdate.save);
inside userUpdate.save I'm calling res.redirect or res.render (different routes but same idea). I don't like this. I'd like to keep my res.* calls in routes.js, but when I attempt this
app.post('/user/:who/update', isLoggedIn, userUpdate.save, function(req, res) {
res.redirect('/user/'+req.user.local.username);
});
with a call to next(req, res) at the end of userUpdate.save, the res.redirect function isn't called. What I think next() is, does not seem to be what it actually is. What am I missing?
The call to next() bypasses the remainder of your callbacks.
See this ref http://expressjs.com/api.html#app.post.method
Take a look at this example and alternately comment out each of the next() calls (and then both of them) and watch where the execution flows.
var express = require('express');
var app = express();
app.get('/test', function(req, res, next){
console.log('/test callback1');
next('route');
//next();
}, function(res, res, next){
console.log('/test callback2');
res.send('sent from /test/cb2')
});
app.get('/test', function(req, res){
console.log('response from /test route handler 2');
res.send('sent from /test route handler 2');
})
var server = app.listen(8911, function (s) {
console.log('Listening on port ', server.address().port);
});

Categories