In an attempt to add a "server-side" state machine service to a single page application of Vue.js (cli), I edited following lines in webpack-dev-server/lib/Server.js:
const app = this.app = new express(); // eslint-disable-line
var globalStore ={ numRequests : 0 };
// I added this by copy-pasting another app.all('/',..) request handler.
app.all('/compute', (req, res, next) => {
globalStore.numRequests++;
res.send("num request="+globalStore.numRequests);
return next();
});
then it gave this warning each time counter is incremented:
(node:12956) UnhandledPromiseRejectionWarning: Error
[ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the
client
Still, it increments the counter, returns it successfully everytime I visit {mydomainname}/compute. Everytime it gives same warning.
I guess I'm making a simple error but can't see. Project was produced by this command:
vue init webpack vueapp01
If I delete "return next" and "res.send ('invalid host header')" lines, no warning is produced. Do I have to call "return" here always?
Related
I created some functions in firebase cloud functions, but all of them are works. But i have a new function which is not work properly. I don't know why but i think it has same pattern with others.
this is my code:
const functions = require('firebase-functions');
const appVideo = express();
const cors = require('cors')({ origin: true });
appVideo.use(cors);
appVideo.get('/update-video', async(req, res) => {
console.log('updateStatusVideo idCourse', req.query.idCourse, ' idMateri: ', req.query.idMateri, ' idVideo:', req.query.idVideo);
res.status(200).send('Oke')
})
exports.video = functions.https.onRequest(appVideo)
I often call partial deploy like
firebase deploy --only functions:video. But when i execute the functions https through browser it often return
Request failed with status code 404
other weird things is when i inspect the browser and switch to console, i found
Failed to load resource: the server responded with a status of 500 ()
this is the url of function in firebase:
https://us-central1-my-apps.cloudfunctions.net/video [modified for confidential]
Please help
When you export this line:
exports.video = functions.https.onRequest(appVideo);
You define a Cloud Function called video that is deployed as https://us-central1-PROJECT_ID.cloudfunctions.net/video where PROJECT_ID is whatever your Firebase Project ID is.
Because you use a express application for this exported function, any URL that is handled must first start with https://us-central1-PROJECT_ID.cloudfunctions.net/video (the BASE_URL).
This line:
appVideo.get('/update-video', ...)
attaches a listener to BASE_URL/update-video, which becomes https://us-central1-PROJECT_ID.cloudfunctions.net/video/update-video.
If you want to use just https://us-central1-PROJECT_ID.cloudfunctions.net/video as-is, you'll need to change to using
appVideo.get('/', ...)
If you want to use just https://us-central1-PROJECT_ID.cloudfunctions.net/update-video, you'll need to change to using
appVideo.get('/', ...)
and
exports.update = {};
exports.update.video = functions.https.onRequest(appVideo);
// "update.video" is deployed as "update-video"
Note: This last part abuses deploying groups to get the desired URL
I have an Express application that runs a blog in a NextJS app, very similar to the example in their repo
I have set it up so that my app runs a query to fetch a blog article, and if the result is empty it throws a NotFoundException.
I catch this exception in my NextJS _error.js file, which is similar to a React error boundary, where I route the user to my 404 page. This part works fine.
The problem I'm having is that this exception is logged to the node console even though I'm not logging it when catching the exception. This pollutes our company's logging software with all our 404's
Is there some node/express setting I'm missing here that prevents the logging of exceptions? Here's my Express process error handler:
process.on('unhandledRejection', (reason, promise) =>
console.error(`Unhandled Rejection at: ${promise}.\nreason: ${reason.stack || reason}`));
I know there is a log there, but the format of the one I want to eliminate is different to this, so I'm confident this is not the source.
I won't pretend to know what's going on, but my best guess is that next.js is logging the error somewhere. I did some digging and it appears there's an error logger in the server code that will log on errors unless a quiet property is set on the server:
https://github.com/zeit/next.js/blob/canary/packages/next-server/server/next-server.ts#L105:
return this.run(req, res, parsedUrl)
.catch((err) => {
this.logError(err)
res.statusCode = 500
res.end('Internal Server Error')
})
Here's the sig and body for the logError function:
private logError(...args: any): void {
if (this.quiet) return
// tslint:disable-next-line
console.error(...args)
}
If you look at the documentation for using the next API with a custom server, it notes the following options object properties that can be passed to the constructor:
The next API is as follows:
next(opts: object)
Supported options:
dev (bool) whether to launch Next.js in dev mode - default false
dir (string) where the Next project is located - default '.'
quiet (bool) Hide error messages containing server information - default false
conf (object) the same object you would use in next.config.js - default {}
When constructing the next object, try passing quiet as true to see if it resolves your issue:
const express = require('express')
const next = require('next')
const port = parseInt(process.env.PORT, 10) || 3000
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev, quiet: true })
const handle = app.getRequestHandler()
The docs also mentions errors are logged in non-production environments (identified when process.env.NODE_ENV !== 'production'), so I would also check to ensure you're setting NODE_ENV to 'production' when starting your application:
NODE_ENV=production node server.js
I hope this helps!
In express you can setup an ErrorMiddleware.
After all your routes declaration, put
server.use(function(req, res, next) {
handler(req, res).catch(e => {
// use rejected promise to forward error to next express middleware
next(e)
})
});
Like this, when you reject a Promise, next(e) will send your error to next middleware. I usually setup a middleware where i send error, and then i manage all errors in one single function (based on statusCode error,...).
I am developing a rest api using express JS . I want to show several error such as route not found, data not found, validation error. I am using async await structure . I need to know how to manage several exception handling in Express JS . I search seveal website but not found exact way . Everywhere write to use nodeJS default exception . But i need it customize in REST API.
I need expert nodejs developer help . If anyone know best resource of express error handling please provide me link to learn this
1.Let for handling route not found error you can use the default route
app.all('/*', (req, res)=> res.status(404).send('Route Not Found'))
2.For handling response, you can set some predefined response in separate module and send all response from that module. Like
//response.js file
module.exports= {
ok : (res, data)=> res.status(200).send({data}),
error: (res, err)=> res.status(err.status).send({error})
}
3.For handling error you can make seperate error file where all error a set and create your error by those listed error. And you can do by try, catch
4.For validation, you can use middleware and or helper for handling validation.
5.Following are some node.js configuration link created by me, you can take reference from there
https://github.com/bapinmalakar/election-exitpoll-back (very simple, Github)
https://github.com/bapinmalakar/pt-backend (little complex, github)
You can log the error using middleware As below given example middleware we can catch the errors which are thrown across the application. Also, we can catch the promise rejections
const express = require("express");
const app = express();
app.use((err, req, res, next) => {
if (err) {
res.status(err.statusCode || 500).send(err);
console.error(err.stack);
next();
}
console.error(`Message :: ${err.message}
Url :: ${req.originalUrl}
Method :: ${req.method}
Ip :: ${req.ip}
Time :: ${(new Date()).toLocaleTimeString()}`);
});
For reference use this link. Click here
I've got a fairly standard connect-mongo setup
mongoose is initialised / connected prior to this
app.use(express.session({
secret: "sfdgsdgsdfg",
store: new MongoSessionStore({db: mongoose.connection.db})
}));
This works fine.
However -
Assuming my mongodb connection suddenly dies (stop mongod locally in the example below)
- the next time I try to hit a route, my express app crashes too -
Error: failed to connect to [localhost:27017]
at null. (/Users/alex/Projects/MyProject/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/server.js:540:74)
at emit (events.js:106:17)
at null. (/Users/alex/Projects/MyProject/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/connection_pool.js:140:15)
at emit (events.js:98:17)
at Socket. (/Users/alex/Projects/MyProject/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/connection.js:478:10)
at Socket.emit (events.js:95:17)
at net.js:440:14
at process._tickCallback (node.js:419:13)
Is there a way to handle this error and (For example) redirect to a /error route?
(Obviously one that doesn't require session!)
EDIT
So now, I'm creating a separate mongoose connection.
I then use the on('error' to listen for errors
...this is where I'm getting stuck -
The process still dies because re-throwing the err doesn't pass it into the express error handler...
var sessionDbConnection = mongoose.createConnection(config.sessionDb);
sessionDbConnection.on('error', function(err) {
console.log('oops');
throw err; //instead of re-throwing the error, i think i need to pass it to the error handler below??
})
app.use(express.session({
secret: "sfdgsdgsdfg",
store: new MongoSessionStore({db: sessionDbConnection.db})
}));
app.use(function(err, req, res, next) {
res.render('error', err); //just for testing
});
Setup a general error handler at the end of your using chain ...
//function must accept 4 arguments
app.use(function(err, req, res, next) {
//use accepts to determin if you should return json, html, image?
//render the appropriate output.
});
Also, have your handlers and other modules accept three parameters (req, res, next) in the case of an error, return next(err) typically you will want to optionally use a .code property to match up your http response code to the one matching the error. using 4xx for input errors, 5xx for server errors etc.
Also, if you want to handle the general case...
process.on('uncaughtException', function(err) {
console.error('Caught exception: ' + err);
console.error(err.stack);
//interrogate the error, if it's something you can recover from, let it be.
//if the exception is fatal, exit with prejudice
setTimeout(process.exit.bind(process, 666), 1000); //exit in a second
});
This will handle your specific case, but you should only allow the process to keep running if its' something that should recover on its' own.
In response to your edit... you could have a global variable that changes when you get a DB error... unfortunately, this error doesn't necessarily happen in the context of an http request.. it could happen before/during/after ... in this way, you cannot know.
If you are using a client that will re-connect on failure, then that will alleviate some issues. The best you can do, is keep track of this variable, serve errors to all requests.. then restart your process.
There are lots of modules from pm2 to forever that will help you with this.
I have this simple code. This must show me my error object ({error:'error'}) upon each request. But it shows only "[Object object]".
And moreover - debugger never stops in the error handler function.
What is going on?
var domain = require('domain');
var express = require('express');
var server = express();
server.get('/', function(req, res)
{
var d = domain.create();
d.on('error', function(e)
{
debugger;
console.log(JSON.stringify(e));
});
d.run(function()
{
throw {error:'error'};
res.send('ok');
});
});
server.listen(8080);
The problem is that domains catch the error all the way at the bottom of the call stack, and since express has its own error handling code, the error gets caught by express before reaching the domain. Similar issue here: Node.js - Domain per Express request, inside another domain
I don't see any particularly good reason it should be this way, but that's how the code seems to work [1] (source here: https://github.com/joyent/node/blob/master/lib/domain.js). Possible workarounds are to surround the d.run() call with your own try/catch, or to do something like
d.run(process.nextTick(function() {
// do stuff
}));
[1] The way domains work is that they basically hook into all of the "asynchronous" callbacks and add some information that records who initiated the asynchronous operation. I don't know why they don't also try/catch on the initial synchronous block.