Node js server crashes after PUT request - node.js

After making a put request, the app crashes with error
[nodemon] restarting due to changes...
[nodemon] starting `node index.js`
(node:21666) DeprecationWarning: current URL string parser is deprecated, and will be removed in a future version. To use the new parser, pass option { useNewUrlParser: true } to MongoClient.connect.
(Use `node --trace-deprecation ...` to show where the warning was created)
Server up and running
(node:21666) DeprecationWarning: Mongoose: `findOneAndUpdate()` and `findOneAndDelete()` without the `useFindAndModify` option set to false are deprecated. See: https://mongoosejs.com/docs/deprecations.html#findandmodify
node:internal/process/promises:227
triggerUncaughtException(err, true /* fromPromise */);
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at new NodeError (node:internal/errors:329:5)
at ServerResponse.setHeader (node:_http_outgoing:572:11)
at ServerResponse.header (/Users/kayode/Desktop/learn-mern/auth/node_modules/express/lib/response.js:771:10)
at ServerResponse.json (/Users/kayode/Desktop/learn-mern/auth/node_modules/express/lib/response.js:264:10)
at ServerResponse.send (/Users/kayode/Desktop/learn-mern/auth/node_modules/express/lib/response.js:158:21)
at /Users/kayode/Desktop/learn-mern/auth/routes/users.js:36:24
at processTicksAndRejections (node:internal/process/task_queues:94:5) {
code: 'ERR_HTTP_HEADERS_SENT'
}
[nodemon] app crashed - waiting for file changes before starting...
Here is my code...
const router = require('express').Router();
const User = require('../models/User')
router.put('/:email', async (req, res, next) => {
res.send(req.params._id)
let email = req.params.email;
let user = {
name: req.body.name,
email: req.body.email,
password: req.body.password
}
try {
await User.findOneAndUpdate(email, user);
res.status(200).send(JSON.stringify('200'));
console.log('Here first')
} catch (err) {
res.status(400).send(err) //not commented
}
})
module.exports = router;
But, if I try to make a another request (with postman), without refreshing the server it says sends a error could not send request
But then again, on line 36, "at /Users/kayode/Desktop/learn-mern/auth/routes/users.js:36:24" where it says res.status(400).send(err) //not commented
if I comment the line out (ie not return an error), the PUT request would be successful and another request after that would also work without refreshing or restartiung the server.
I know I can just comment that line out and move on, but I need to know what's happening, thanks!

You are sending the response in the beginning of the request and try to send it again in the end of the request (in line5) .
const router = require('express').Router();
const User = require('../models/User')
router.put('/:email', async (req, res, next) => {
let email = req.params.email;
let user = {
name: req.body.name,
email: req.body.email,
password: req.body.password
}
try {
await User.findOneAndUpdate(email, user);
res.status(200).send(JSON.stringify('200'));
console.log('Here first')
} catch (err) {
res.status(400).send(err) //not commented
}
})
module.exports = router;

Related

unable to change password using mongoose

I am using MongoDB, mongoose, ejs and NodeJS for my site. I have a update password function which is not working properly. I have checked again and again by login different things in console and there is no problem in getting data in req. So I guess my problem is in the controller. This is my controller:
module.exports.update_password = function (req, res) {
console.log(req.user);
Company.findOne({ username: req.user.username }, function (err, user) {
if (user.password == req.body.current_password) {
if (req.body.new_password == req.body.confirm_password) {
Company.findOneAndUpdate({ username: req.user.username }, { password: req.body.new_password }, { upsert: true }, function (err, doc) {
if (err) return res.send(500, { error: err });
req.flash('notify', 'Password changed!')
return res.redirect('/profile');
});
}
else req.flash('notify', 'New password does not match with confirm password');
}
else req.flash('notify', '!')
});
return res.redirect('/profile');
}
everytime updating my password I get this error:
node:events:355
throw er; // Unhandled 'error' event
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at new NodeError (node:internal/errors:329:5)
at ServerResponse.setHeader (node:_http_outgoing:573:11)
at ServerResponse.header (/home/krush/github/Project_Lightspeed/node_modules/express/lib/response.js:771:10)
at ServerResponse.location (/home/krush/github/Project_Lightspeed/node_modules/express/lib/response.js:888:15)
at ServerResponse.redirect (/home/krush/github/Project_Lightspeed/node_modules/express/lib/response.js:926:18)
at /home/krush/github/Project_Lightspeed/controllers/authentication_controller.js:45:32
at /home/krush/github/Project_Lightspeed/node_modules/mongoose/lib/model.js:4857:16
at /home/krush/github/Project_Lightspeed/node_modules/mongoose/lib/model.js:4857:16
at /home/krush/github/Project_Lightspeed/node_modules/mongoose/lib/helpers/promiseOrCallback.js:24:16
at /home/krush/github/Project_Lightspeed/node_modules/mongoose/lib/model.js:4880:21
at /home/krush/github/Project_Lightspeed/node_modules/mongoose/lib/query.js:4397:11
at /home/krush/github/Project_Lightspeed/node_modules/kareem/index.js:136:16
at processTicksAndRejections (node:internal/process/task_queues:76:11)
Emitted 'error' event on Function instance at:
at /home/krush/github/Project_Lightspeed/node_modules/mongoose/lib/model.js:4859:13
at /home/krush/github/Project_Lightspeed/node_modules/mongoose/lib/helpers/promiseOrCallback.js:24:16
[... lines matching original stack trace ...]
at processTicksAndRejections (node:internal/process/task_queues:76:11) {
code: 'ERR_HTTP_HEADERS_SENT'
}
[nodemon] app crashed - waiting for file changes before starting...
It seems that the problem is that the return res.redirect('/profile'); command is executed before your callback functions. Which is normal since this is how the event loop works.
Try to remove the return res.redirect('/profile'); line to see if the error goes away. Callbacks at node.js execute at a later stage of the event loop.
Generally I would recommend to refactor your code to use promises instead of callbacks since that causes the "callback hell" anti-pattern.
If you refactor your code to use promises, then you will be able to use .then or async await, which will help you write cleaner code and help you spot any error easily.

(node:23977) UnhandledPromiseRejectionWarning: Error: Missing credentials for "PLAIN"

I'm trying to send emails from the site to the post office Mail.ru, but the following error appears:
(node:25258) UnhandledPromiseRejectionWarning: Error: Missing credentials for "PLAIN"
at SMTPConnection._formatError (/home/user/server/node_modules/nodemailer/lib/smtp-connection/index.js:784:19)
at SMTPConnection.login (/home/user/server/node_modules/nodemailer/lib/smtp-connection/index.js:448:38)
at /home/user/server/node_modules/nodemailer/lib/smtp-transport/index.js:271:32
at SMTPConnection.<anonymous> (/home/user/server/node_modules/nodemailer/lib/smtp-connection/index.js:215:17)
at Object.onceWrapper (events.js:421:28)
at SMTPConnection.emit (events.js:315:20)
at SMTPConnection._actionEHLO (/home/user/server/node_modules/nodemailer/lib/smtp-connection/index.js:1313:14)
at SMTPConnection._processResponse (/home/user/server/node_modules/nodemailer/lib/smtp-connection/index.js:942:20)
at SMTPConnection._onData (/home/user/server/node_modules/nodemailer/lib/smtp-connection/index.js:749:14)
at TLSSocket.SMTPConnection._onSocketData (/home/user/server/node_modules/nodemailer/lib/smtp-connection/index.js:195:44)
(node:25258) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:25258) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
And here is the backend code itself:
const express = require('express');
const nodemailer = require('nodemailer');
const Parser = require('body-parser');
const sqlite3 = require('sqlite3').verbose();
const server = express();
let path_services = ( __dirname + '/public/static/img/services/' );
let path_html = ( __dirname + '/public/index.html' );
let path_font = ( __dirname + '/public/static/font/' );
let path_css = ( __dirname + '/public/static/css/' );
let path_img = ( __dirname + '/public/static/img/' );
let path_js = ( __dirname + '/public/static/js/' );
let path_db = ( __dirname + '/Main.db' );
const Body_Parser = Parser.urlencoded({extended: false});
server.get('/', Body_Parser , function(request, response) {
response.sendFile(path_html);
});
server.post('/', Body_Parser, function(request, response) {
let db = new sqlite3.Database(path_db, sqlite3.OPEN_READWRITE, (err) => {
if(err) {
console.error(err.message);
}
console.log('Connected to Database!');
});
db.run('INSERT INTO Client(firstname, lastname, email, phone, message) VALUES($firstname, $lastname, $email, $phone, $message)', {
$firstname: request.body.ghostName,
$lastname: request.body.ghostSurname,
$email: request.body.ghostEmail,
$phone: request.body.ghostPhone,
$message: request.body.ghostMessage
}, function(err) {
if(err) {
console.log(err.message);
}
console.log('Good!');
response.end('Ok!');
});
db.close();
let testEmailAccount = nodemailer.createTestAccount();
let transporter = nodemailer.createTransport({
service: 'email',
host: 'smtp.ethereal.email',
port: 587,
secure: false,
auth: {
type: "login", // default
user: testEmailAccount.user,
pass: testEmailAccount.pass
}
});
let result = transporter.sendMail({
from: '"Node js" <nodejs#example.com>',
to: "chrome_777111777#mail.ru",
subject: "Message from Node js",
text: "This message was sent from Node js server.",
html: "This <i>message</i> was sent from <strong>Node js</strong> server."
});
console.log(result);
});
server.use(express.static (path_services) );
server.use(express.static (path_font) );
server.use(express.static (path_css) );
server.use(express.static (path_img) );
server.use(express.static (path_js) );
server.listen(8000);
I am asking you for help, because I have already visited a huge number of sites (starting with the official documentation and ending with a lot of unfamiliar forums), but everywhere I went it was said about sending emails to Gmail, about sending emails to email was said only in the documentation and on several other sites that copied information from the documentation. I will be very grateful to you if you help!
nodemailer.createTestAccount is an async function, that means, you just have to put the await keyword in front of it like that:
let testEmailAccount = await nodemailer.createTestAccount();
Otherwise testEmailAccount is a promise and testEmailAccount.user and testEmailAccount result as undefined.
In your case you also have to make your app.post callback an async function:
server.post('/', Body_Parser, async function(request, response) {
// ...
}

how did this forked in the rest api route go wrong?

Update: This problem was solved. I followed the advice of the replies and tried the console.log(req.body) command. Turns out it was calling a different function. Now at the time I was using postman to test the API and I learned that editing an already saved function is not the same as with other text or media editors and you have to make a completely new function to test it. I.E. I used a previous post function to create user and changed some elements, turns out postman doesnt like that and just ran the old function.
Thanks for the help everyone
I made an admin route using an already working user route exactly except using fewer values.
I keep getting an undefined error during validation when ever I try to run a post function. what could have gone wrong here? Or where should I look for the error, I checked the spellings of each of the values Iam using in the create admin function but I see no spelling problems?
Error in Console:
Error: admin validation failed: AdminEMail: Path `AdminEMail` is required., AdminPassword: Path `AdminPassword` is required.
at ValidationError.inspect (D:\Downloads\Compressed\api-master_3\api-master\node_modules\mongoose\lib\error\validation.js:48:26)
at formatValue (internal/util/inspect.js:563:31)
at inspect (internal/util/inspect.js:221:10)
at formatWithOptions (internal/util/inspect.js:1693:40)
at Object.Console.<computed> (internal/console/constructor.js:272:10)
at Object.log (internal/console/constructor.js:282:61)
at D:\Downloads\Compressed\api-master_3\api-master\routes\Admin.js:25:21
at D:\Downloads\Compressed\api-master_3\api-master\node_modules\mongoose\lib\model.js:4876:16
at D:\Downloads\Compressed\api-master_3\api-master\node_modules\mongoose\lib\helpers\promiseOrCallback.js:16:11
at D:\Downloads\Compressed\api-master_3\api-master\node_modules\mongoose\lib\model.js:4899:21
at D:\Downloads\Compressed\api-master_3\api-master\node_modules\mongoose\lib\model.js:493:16
at D:\Downloads\Compressed\api-master_3\api-master\node_modules\kareem\index.js:246:48
at next (D:\Downloads\Compressed\api-master_3\api-master\node_modules\kareem\index.js:167:27)
at next (D:\Downloads\Compressed\api-master_3\api-master\node_modules\kareem\index.js:169:9)
at Kareem.execPost (D:\Downloads\Compressed\api-master_3\api-master\node_modules\kareem\index.js:217:3)
at _handleWrapError (D:\Downloads\Compressed\api-master_3\api-master\node_modules\kareem\index.js:245:21) {
errors: {
AdminEMail: ValidatorError: Path `AdminEMail` is required.
at validate (D:\Downloads\Compressed\api-master_3\api-master\node_modules\mongoose\lib\schematype.js:1178:13)
at D:\Downloads\Compressed\api-master_3\api-master\node_modules\mongoose\lib\schematype.js:1161:7
at Array.forEach (<anonymous>)
at SchemaString.SchemaType.doValidate (D:\Downloads\Compressed\api-master_3\api-master\node_modules\mongoose\lib\schematype.js:1106:14)
at D:\Downloads\Compressed\api-master_3\api-master\node_modules\mongoose\lib\document.js:2379:18
at processTicksAndRejections (internal/process/task_queues.js:76:11) {
properties: [Object],
kind: 'required',
path: 'AdminEMail',
value: undefined,
reason: undefined,
[Symbol(mongoose:validatorError)]: true
},
AdminPassword: ValidatorError: Path `AdminPassword` is required.
at validate (D:\Downloads\Compressed\api-master_3\api-master\node_modules\mongoose\lib\schematype.js:1178:13)
at D:\Downloads\Compressed\api-master_3\api-master\node_modules\mongoose\lib\schematype.js:1161:7
at Array.forEach (<anonymous>)
at SchemaString.SchemaType.doValidate (D:\Downloads\Compressed\api-master_3\api-master\node_modules\mongoose\lib\schematype.js:1106:14)
at D:\Downloads\Compressed\api-master_3\api-master\node_modules\mongoose\lib\document.js:2379:18
at processTicksAndRejections (internal/process/task_queues.js:76:11) {
properties: [Object],
kind: 'required',
path: 'AdminPassword',
value: undefined,
reason: undefined,
[Symbol(mongoose:validatorError)]: true
}
},
_message: 'admin validation failed'
}
And Here is the route:
//Imported modules
const express = require('express');
const router = express.Router();
const mongoose = require('mongoose');
//Imported models
const Admin = require('../models/admin');
//const User = require('../models/user');
router.get('/', (req,res) =>{
res.send("We are on Admin");
})
//Admin Functions
//Creation of new Admin
router.post("/signup", (req,res) => {
const admin = new Admin({
_id: new mongoose.Types.ObjectId(),
AdminEMail: req.body.AdminEMail,
AdminPassword: req.body.AdminPassword
});
admin.save(function(err,admin){
if(err){
console.log(err);
res.send(err);
return
}
console.log("New admin created");
res.send(admin);
})
})
//Admin Login and verification
router.post("/login", (req,res) => {
const AdminID = req.body.AdminID;
const Username = req.body.username;
const Password = req.body.password;
Admin.findOne({_id:AdminID}, function(err, foundAdmin){
if(err){
res.send("<h1>got clicked</h1>");
console.log(err);
}else{
if(foundAdmin){
if(foundAdmin.AdminEMail === Username){
if(foundAdmin.AdminPassword === Password){
res.send("logged in");
}
else{
res.send("Username and Password Mismatch");
}
}
else{
res.send("Username and ID Mismatch");
}
}
else{
res.send("No Such admin exists");
}
}
});
});
//
module.exports = router;

how can i parse a error message that i am getting in nodejs app

I am making an app with reactjs frontend and nodejs backend api for that at someplace i getting error something like this.
But here i want to get only this message email: {message: "This email is already taken", I tried to parse this error using some online turorial but when i try them i get error from backend.
This is the error after using errorparser
(node:14208) UnhandledPromiseRejectionWarning: ReferenceError: errors is not defined
at exports.default (C:/projects/bookworm-practice/bookworm-api/src/utils/parseErrors.js:5:15)
at C:/projects/bookworm-practice/bookworm-api/src/routes/users.js:14:54
at process._tickCallback (internal/process/next_tick.js:68:7)
(node:14208) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:14208) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
this is my parseError function
import _ from 'lodash';
export default function () {
const result = {};
_.forEach(errors, (val, key) => {
result[key] = val.message;
});
return result;
}
this is my user function where i am using parseError
import express from 'express';
import User from '../models/User';
import parseErrors from '../utils/parseErrors';
const router = express.Router();
router.post('/', (req, res) => {
const { email, password } = req.body.user;
const user = new User({ email });
user.setPassword(password);
user.save()
.then(user => res.json({ user: user.toAuthJSON() }))
//.catch(err => res.json({ err })); // this is the default one
.catch(err => res.status(400).json({ errors: parseErrors(err.errors)
//this is after adding parseErrors funtion
}))
})
export default router;
Your parseErrors function did not includes errors as argument
import _ from 'lodash';
export default function (errors) {
const result = {};
_.forEach(errors, (val, key) => {
result[key] = val.message;
});
return result;
}

Keep getting the "ConfigError: Missing region in config" error in Node.js no matter what I do

I keep getting the "UnhandledPromiseRejectionWarning: ConfigError: Missing region in config" when trying to make requests to APIs I have set up in Node.js.
I'm new to DynamoDB and after setting up most of my boilerplate code I'm using Postman to test my routes. However I keep getting the same error each time I make a post request. I've checked some solutions on existing threads, namely: Configuring region in Node.js AWS SDK but cannot get it to work.
I am currently developing the app locally and checked the database where the items are being added.
My setup is as follows:
// user_controller.js
const uuid = require('uuid');
const sanitizer = require('validator');
const bcrypt = require('bcryptjs-then');
const AWS = require('aws-sdk');
const config = require('../config/config');
const { signToken, userByEmail, userById } = require('../Helpers/Users');
const isDev = true
Then in my code block I have the following:
// user_controller.js
(...)
if (isDev) {
AWS.config.update(config.aws_local_config);
} else {
AWS.config.update(config.aws_remote_config);
}
const DB = new AWS.DynamoDB.DocumentClient();
const params = {
TableName: config.aws_table_name,
Item: {
userId: await uuid.v1(),
firstName: sanitizer.trim(firstName),
lastName: sanitizer.trim(lastName),
email: sanitizer.normalizeEmail(sanitizer.trim(email)),
password: await bcrypt.hash(password, 8),
level: 'standard',
createdAt: new Date().getTime(),
updatedAt: new Date().getTime(),
},
}
return userByEmail(params.Item.email) // Does the email already exist?
.then(user => { if (user) throw new Error('User with that email exists') })
.then(() => DB.put(params).promise()) // Add the data to the DB
.then(() => userById(params.Item.id)) // Get user data from DB
.then(user => (err, data) => {
console.log("AFTER USER CREATED")
if (err) {
res.send({
success: false,
message: 'Error: Server error'
});
} else {
console.log('data', data);
res.send({
statusCode: 201,
message: 'Success - you are now registered',
data: { token: signToken(params.Item.id), ...user },
});
}
})
(...)
Finally I am importing the config from separate file:
// config.js
module.exports = {
aws_table_name: 'usersTable',
aws_local_config: {
region: 'local',
endpoint: 'http://localhost:8000'
},
aws_remote_config: {}
}
In have already configured the aws-sdk:
AWS Access Key ID [****************foo]:
AWS Secret Access Key [****************bar]:
Default region name [local]:
Default output format [json]:
Here is the output I keep getting:
(node:4568) UnhandledPromiseRejectionWarning: ConfigError: Missing region in config
at Request.VALIDATE_REGION (/Users/BANGBIZ/Programming/techstars/capexmove/SmartLegalContract/node_modules/aws-sdk/lib/event_listeners.js:92:45)
at Request.callListeners (/Users/BANGBIZ/Programming/techstars/capexmove/SmartLegalContract/node_modules/aws-sdk/lib/sequential_executor.js:106:20)
at callNextListener (/Users/BANGBIZ/Programming/techstars/capexmove/SmartLegalContract/node_modules/aws-sdk/lib/sequential_executor.js:96:12)
at /Users/BANGBIZ/Programming/techstars/capexmove/SmartLegalContract/node_modules/aws-sdk/lib/event_listeners.js:86:9
at finish (/Users/BANGBIZ/Programming/techstars/capexmove/SmartLegalContract/node_modules/aws-sdk/lib/config.js:350:7)
at /Users/BANGBIZ/Programming/techstars/capexmove/SmartLegalContract/node_modules/aws-sdk/lib/config.js:368:9
at SharedIniFileCredentials.get (/Users/BANGBIZ/Programming/techstars/capexmove/SmartLegalContract/node_modules/aws-sdk/lib/credentials.js:127:7)
at getAsyncCredentials (/Users/BANGBIZ/Programming/techstars/capexmove/SmartLegalContract/node_modules/aws-sdk/lib/config.js:362:24)
at Config.getCredentials (/Users/BANGBIZ/Programming/techstars/capexmove/SmartLegalContract/node_modules/aws-sdk/lib/config.js:382:9)
at Request.VALIDATE_CREDENTIALS (/Users/BANGBIZ/Programming/techstars/capexmove/SmartLegalContract/node_modules/aws-sdk/lib/event_listeners.js:81:26)
(node:4568) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 4)
(node:4568) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Like I said, I've tried a lot of variations on this but to no avail. Would love some help, thanks.
I dont know if this helps, but I used none instead of local for the region and it seemed to work for me
AWS.config.update({ region: 'none' })

Resources