ExpressJS breaking when trying to serve missing images - node.js

ExpressJS Newbie Warning
I have a simple server running with expressjs and all works well when all images are present. But if an image is missing expressjs stops with the following error
(node:5793) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Cannot find module 'jpg'
This is preventing anything else from loading, or even an links working. The page just hangs there. Shouldn't it simple not serve the image (send a 404) and still allow the site to work?
UPDATE
router.get('/*', (req, res, next) => {
dynamicStatic.setPath(path.resolve(__dirname, 'public/templates/' +
app.get('templatePath')));
res.render('index');
});
I use dynamicStatic because I need to be able to set the path dynamically based on some conditions. This sets express.static under the hood. I don't think that has anything to do with it because other images are being served fine. Of course I could be wrong, though.
UPDATE 2
The images remain in a (pending) state which is where the hang up is coming from.
This image shows the error messages I receive in Node/Express.

I think catching the exception with a try {} catch block should do the job just fine.
Put the code that could throw an exception in the try block and if an exception is thrown send the 404 status.
Here’s a try:
router.get('/*', (req, res, next) => {
try {
dynamicStatic.setPath(path.resolve(__dirname, 'public/templates/' +
app.get('templatePath')));
res.render('index');
} catch(err) {
res.sendStatus(404);
}
});

Related

res.download() throw Request aborted

I'm using express and trying to download a file, then load the page. I understood that the problem is stopping res.download with res.render but I can' t figure out how to resolve this. I also tried to put res.render() inside the callback function of res.download(), the only thing that happen is that res.render stopped working but the file would download.
app.get("/", function(req, res) {
res.download(
"./public/sample-zip/Lost Sky - Dreams.zip",
"Lost Sky - Dreams.zip",
err => {
if (err) console.log("Errore nel dw: " + err);
}
);
res.render("index");
});
You can't end the same request in multiple ways - download behind the scenes will call sendFile which sends a file to the client and ends the request, similarly render will send page content and also end the request.
The correct approach here is to allow the file to be downloaded to the client and then have the client redirect the page on the back of a successful download.

too many redirects in express

I want to handle all my cookies and session stuff in a function then redirect to the destination path. I use this function in Express:
app.all('*', function(req, res, next){
if('_id' in req.session)
next()
else if('userInfo' in req.cookies){
req.session._id = req.cookies.userInfo._id
next()
} else {
res.redirect('../login')
}
res.end()
})
but browser print this error:
net::ERR_TOO_MANY_REDIRECTS
what's the problem?
This error occurs when a web browser is redirecting you to another web page which then that web page redirects you back to the same browser again. Your configurations are wrong. app.all('*', ..) runs again and again whenever a request is made, which causing repetition.
You need to have better configurations than app.all(*..) //all. You need to specify it more so that it doesn't repeat itself.
I would say limit it down to some urls and not all of them. You could do
app.get('/cookieCheckerPage', function(req, res){
//code here
});
Also please see Error 310 (net::ERR_TOO_MANY_REDIRECTS):

Remove nodejs error dump

everytime I have a critical error which terminates the server on NodeJS which comes from a request of a client, he gets the error dump.
How can I change this behaviour ?
I assume you are talking about Express.js. Error stack trace is sent to client when environment is not production (please refer Express docs).
To disable this behavior, you should set NODE_ENV environmental variable
to production.
You can process the error - more common is 404 and 500.
Follow one example to do this (in case express):
exports.notFound = function(req, res, next) {
res.status(404);
res.render('not-found');
};
exports.serverError = function(error, req, res, next) {
res.status(500);
res.render('server-error', {error: error});
};
And create the files not-found and server-error (EJS or Jade for example) for show custom page in case of error.

ExpressJS : res.redirect() not working as expected?

I've been struggling for 2 days on this one, googled and stackoverflowed all I could, but I can't work it out.
I'm building a simple node app (+Express + Mongoose) with a login page that redirects to the home page. Here's my server JS code :
app
.get('/', (req, res) => {
console.log("Here we are : root");
return res.sendfile(__dirname + '/index.html');
})
.get('/login', (req, res) => {
console.log("Here we are : '/login'");
return res.sendfile(__dirname + '/login.html');
})
.post('/credentials', (req, res) => {
console.log("Here we are : '/credentials'");
// Some Mongoose / DB validations
return res.redirect('/');
});
The login page makes a POST request to /credentials, where posted data is verified. This works. I can see "Here we are : '/credentials'" in the Node console.
Then comes the issue : the res.redirect doesn't work properly. I know that it does reach the '/' route, because :
I can see "Here we are : root" in the Node console
The index.html page is being sent back to the browser as a reponse, but not displayed in the window.
Chrome inspector shows the POST request response, I CAN see the HTML code being sent to the browser in the inspector, but the URL remains /login and the login page is still being displayed on screen.
(Edit) The redirection is in Mongoose's callback function, it's not synchronous (as NodeJS should be). I have just removed Mongoose validation stuff for clarity.
I have tried adding res.end(), doesn't work
I have tried
req.method = 'get';
res.redirect('/');
and
res.writeHead(302, {location: '/'});
res.end();
Doesn't work
What am I doing wrong? How can I actually leave the '/login' page, redirect the browser to '/' and display the HTML code that it received?
Thanks a million for your help in advance :)
The problem might not lie with the backend, but with the frontend. If you are using AJAX to send the POST request, it is specifically designed to not change your url.
Use window.location.href after AJAX's request has completed (in the .done()) to update the URL with the desired path, or use JQuery: $('body').replaceWith(data) when you receive the HTML back from the request.
If you are using an asynchronous request to backend and then redirecting in backend, it will redirect in backend (i.e. it will create a new get request to that URL), but won't change the URL in front end.
To make it work you need to:
use window.location.href = "/url"
change your async request (in front end) to simple anchor tag (<a></a>)
It's almost certain that you are making an async call to check Mongoose but you haven't structured the code so that the redirect only happens after the async call returns a result.
In javascript, the POST would look like something this:
function validateCredentials(user, callback){
// takes whatever you need to validate the visitor as `user`
// uses the `callback` when the results return from Mongoose
}
app.post('/credentials', function(req, res){
console.log("Here was are: '/credentials'";
validateCredentials(userdata, function(err, data){
if (err) {
// handle error and redirect to credentials,
// display an error page, or whatever you want to do here...
}
// if no error, redirect
res.redirect('/');
};
};
You can also see questions like Async call in node.js vs. mongoose for parallel/related problems...
I've been working on implementing nodemailer into my NextJS app with Express. Was having this issue and came across this. I had event.preventDefault() in my function that was firing the form to submit and that was preventing the redirect as well, I took it off and it was redirecting accordingly.
Add the following in your get / route :
res.setHeader("Content-Type", "text/html")
Your browser will render file instead of downloading it

How do you catch all errors in SailsJS

I'm new to Node and Sails and have been struggling with this problem for a couple of weeks now. I need to log (eventually to a file or database) all errors that occur in our Sails app. I have found a couple of answers that come close to solving this, but none seem to work 100%. I have setup things based off of the answer from this question
When using Sails v0.9.16 I setup my logging in the config/500.js file, but when using test code...
t.t;
... in my controller, Sails just prints out "ReferenceError: t is not defined". It never goes to 500.js. In Sails v0.10.0-rc5 the same test code will get to my custom 500 middleware (shown below).
Problem is in Sails v0.10.0-rc5 it appears that the middleware Router handles 400 error message before getting to my custom 400 middleware.
We have not committed to which version we are going to use, but getting this to work in one or the other would probably make up our minds.
So how do I get all errors that happen? If I am on the right track, what am I missing to get this to work?
Thanks in advance!
Not much code to show for v0.9.16...I don't think I changed anything other than adding a sails.log in the 500.js file...
Below is the custom middleware setup for v0.10.0-rc5 ...
loadMiddleware: function(app, defaultMiddleware, sails) {
// Use the middleware in the correct order
app.use(defaultMiddleware.startRequestTimer);
app.use(defaultMiddleware.cookieParser);
app.use(defaultMiddleware.session);
app.use(defaultMiddleware.bodyParser);
app.use(defaultMiddleware.handleBodyParserError);
app.use(defaultMiddleware.methodOverride);
app.use(defaultMiddleware.poweredBy);
app.use(defaultMiddleware.router); //400s do not make it past this...
app.use(defaultMiddleware.www);
app.use(defaultMiddleware.favicon);
app.use(function(req, res, next ) {
sails.log("400 error caught in middleware - " + err.stack);
next();
});
app.use(function(err, req, res, next){
sails.log("500 error caught in middleware - " + err.stack);
next(err);
});
}
In Sails v0.10, you have custom responses to handle errors, so you don't need to provide custom middleware as in your example. By default, most errors (i.e. those not specifically triggered by res.forbidden(), res.notFound() or another handler) will be served by the serverError response that lives in api/responses/serverError.js. You can customize this to do whatever you like.
If you've upgraded a v0.9 app to v0.10, you might not have the api/responses folder. No problem; just use sails new whatever in an empty directory to generate a new v0.10 project and copy the api/responses folder from the new project to your old one!

Resources