PATCH route/endpoint in Express not working - node.js

Hi I've written the following route for an api endpoint which isn't working. When I test with Postman and my code, it's simply a 404 not found error.
router.patch("/favorite", async (req, res) => {
user = await User.findById(req.body.id)
if (user == null) {
return res.status(404).json({ message: 'Cannot find user' })
}
if (req.body.putArr != null) {
res.user.favPokemon = req.body.putArr;
}
try {
const updatedUser = await res.user.save();
console.log(res.user.favPokemon);
console.log(updateUser);
res.json(updatedUser);
} catch (err) {
res.status(400).json({ error: err.message });
}
});
What am I missing/what error do I have in my code? For reference, here's my mongoDB setup for users:
Edit: Apologies for not specifying the endpoint. To be more clear, the end point and code calling this is:
const favThis = async (e) => { // Patch method to favorite or unfavorite a pokemon
debugger;
e.preventDefault();
try {
console.log(putArr);
const newUser = {userID, putArr};
await axios.patch("http://localhost:5000/users/favorite", newUser);
} catch(err) {
err.response.data.msg && setError(err.response.data.msg)
}
};
, so it's http://localhost:5000/users/favorite. I have other endpoints working fine such as http://localhost:5000/users/login and http://localhost:5000/users/register, and inside server.js I have app.use("/users", require("./routes/users"));
Additionally, server.js is simply
const express = require("express");
const mongoose = require("mongoose");
const cors = require("cors");
require("dotenv").config();
// set up express
const app = express();
app.use(express.json());
app.use(cors());
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`The server has started on port: ${PORT}`));
// set up mongoose
mongoose.connect(
process.env.MONGODB_CONNECTION_STRING,
{
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
},
(err) => {
if (err) throw err;
console.log("MongoDB connection established");
}
);
// set up routes
app.use("/users", require("./routes/users"));
app.use("/todos", require("./routes/todo"));
Edit 2:: I notice now that when I test on Postman, it's an infinite loop and the call is hung. I also get the following warnings in my console:
(node:36447) 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)
and
(node:36447) [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.

Based on the warning you have failing code inside a promise which is not being caught. Perhaps in this line user = await User.findById(req.body.id).
Getting a UnhandledPromiseRejectionWarning when testing using mocha/chai

Related

Incomplete response received from application - Deployment NodeJS Express & MongoDB Web Application

I built a NodeJS Express & MongoDB web application that is working well locally.
I tried to deploy it.
Eventhough, the application is partially working in production mode, some of its pages are not displaying.
For example, I'm not able to access the blog page and the following message error displays instead of the content of the page:
Incomplete response received from application
Therefore, I logged the blog page and got the error message below:
App 814821 output: node:internal/process/promises:279 App 814821
output: triggerUncaughtException(err, true /* fromPromise /); App
814821 output: ^ App 814821 output: [UnhandledPromiseRejection: 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(). The promise rejected with the reason "#".] {
App 814821 output: code: 'ERR_UNHANDLED_REJECTION' App 814821 output:
} [ W 2022-11-19 10:30:01.7998 813657/Tg
age/Cor/Con/InternalUtils.cpp:96 ]: [Client 5-1] Sending 502 response:
application did not send a complete response [ N 2022-11-19
10:30:01.8095 813657/Ti age/Cor/CoreMain.cpp:1147 ]: Checking whether
to disconnect long-running connections for process 814821, application
/home/raso1970/node-com4muz (development) App 815207 output:
node:internal/process/promises:279 App 815207 output:
triggerUncaughtException(err, true / fromPromise */); App 815207
output: ^ App 815207 output: [UnhandledPromiseRejection: 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(). The promise rejected with the reason "#".] { App
815207 output: code: 'ERR_UNHANDLED_REJECTION' App 815207 output: } [
W 2022-11-19 10:30:03.7100 813657/Ti age/Cor/Con/InternalUtils.cpp:96
]: [Client 6-1] Sending 502 response: application did not send a
complete response [ W 2022-11-19 10:30:05.0596 813657/T3
age/Cor/App/Poo/AnalyticsCollection.cpp:102 ]: Process (pid=815207,
group=/home/raso1970/node-com4muz (development)) no longer exists!
Detaching it from the pool. [ N 2022-11-19 10:30:05.0597 813657/T3
age/Cor/CoreMain.cpp:1147 ]: Checking whether to disconnect
long-running connections for process 815207, application
/home/raso1970/node-com4muz (development)
I guess the issue comes from MongoDB?
Maybe I did not set up the connection correctly?
Here is my code related to the MongoDB database connection:
data\database.js:
const mongodb = require('mongodb');
const MongoClient = mongodb.MongoClient;
let database;
let mongodbUrl = 'mongodb://127.0.0.1:27017';
let MONGODB_URL = 'mongodb+srv://<username>:<password>#cluster0.42o6qd6.mongodb.net/?retryWrites=true&w=majority'
if (process.env.MONGODB_URL) {
mongodbUrl = process.env.MONGODB_URL;
}
async function connect() {
const client = await MongoClient.connect(mongodbUrl);
database = client.db('com4muz-blog');
}
function getDb() {
if (!database) {
throw { message: 'Database connection not established!' };
}
return database;
}
module.exports = {
connectToDatabase: connect,
getDb: getDb
};
Indeed, I did write my username and password instead of <username> and <password> to the MONGODB_URL value.
app.js:
const path = require('path');
const express = require('express');
const session = require('express-session');
const sessionConfig = require('./config/session');
const db = require('./data/database');
const adminRoutes = require('./routes/admin/blog');
const authRoutes = require('./routes/admin/auth');
const defaultRoutes = require('./routes/home/default');
const postsRoutes = require('./routes/home/posts');
const quotationsRoutes = require('./routes/home/quotations');
const contactsRoutes = require('./routes/home/contacts');
const authMiddleware = require('./middlewares/auth-middleware');
const mongoDbSessionStore = sessionConfig.createSessionStore(session);
let port = 3000;
if (process.env.MONGODB_URL) {
port = process.env.MONGODB_URL;
}
const app = express();
app.set('views', [
path.join(__dirname, 'views/home'),
path.join(__dirname, 'views/admin')
]);
app.set('view engine', 'ejs');
app.use(express.static('public'));
app.use('/public/admin/images', express.static('public/admin/images'));
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(session(sessionConfig.createSessionConfig(mongoDbSessionStore)));
app.use(authMiddleware);
app.use('/', adminRoutes);
app.use('/', authRoutes);
app.use('/', defaultRoutes);
app.use('/', postsRoutes);
app.use('/', quotationsRoutes);
app.use('/', contactsRoutes);
app.use(function (req, res) {
res.status(404).render('404');
});
app.use(function (error, req, res, next) {
console.error(error);
res.status(500).render('500');
});
if (typeof(PhusionPassenger) !== 'undefined') {
PhusionPassenger.configure({ autoInstall: false });
}
if (typeof(PhusionPassenger) !== 'undefined') {
app.listen('passenger');
} else {
app.listen(3000);
}
I'm using o2switch as a hosting server. They use the Setup Node.js App tool, which deploy the website through Phushion Passenger.

504 on Node.JS frontend Azure AppService calling C# API backend Azure AppService

We have a frontend using ExpressJS server and talk to a backend on .NET 5. Both frontend and backend are running on separate Azure AppService.
FE: https://my-front-end.azurewebsites.net
BE: https://my-back-end.azurewebsites.net
Whenever we try to call the backend from frontend, it will always return 504 Gateway Timeout.
We try to add a simple /hello endpoint on the FE side and we could see {"message":"Hello World!"} is printed out. But the other endpoints, for example api/vessels/3 will get 504 - Gateway Timeout
const dotenv = require('dotenv');
const express = require('express');
const axios = require('axios');
const cors = require('cors');
const bodyParser = require('body-parser');
// import path from 'path';
dotenv.config();
const app = express();
const port = process.env.PORT || 1337; // default port to listen
app.use(cors());
app.use(function(_, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'X-Requested-With');
next();
});
app.use(bodyParser.json());
app.use(express.static(process.cwd() + '/ui/build/'));
// define a route handler for the default home page
app.get('/', (_, res) => {
res.sendFile(process.cwd() + '/ui/build/index.html');
});
app.get('/hello', (_, res) => {
res.status(200).send({ message: "Hello World!" });
});
const getHeaders = (domain = 'ABC') => {
return {
'Content-Type': 'application/json',
'cp-site-domain': domain
}
};
const http = axios.create({
baseURL: process.env.API_API_URL,
timeout: process.env.REQUEST_TIMEOUT
});
app.get('/api/vessels/:orgId', async (req, res) => {
const { orgId } = req.params;
const { data } = await http.get(`/Vessels?organizationId=${orgId}`, {
headers: getHeaders()
});
res.status(200).send(data);
});
// start the Express server
app.listen(port, () => {
console.log(`server started at http://localhost:${ port }`);
});
The error log from iisnode is:
(node:9880) UnhandledPromiseRejectionWarning: Error: connect EACCES 127.0.0.1:80
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16)
at TCPConnectWrap.callbackTrampoline (internal/async_hooks.js:130:17)
(node:9880) 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: 2)
(node:9880) [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.
There is no problem if the backend APIs are being called directly from the UI (the usual AJAX). The error only happen when the request to BE is being triggered by ExpressJS.
Do we need to configure something on NodeJS or on Azure AppService side?
I found the solution to this problem.
It turns out, the problem is related to the environment variable. On the local development, we are using dotenv that loads environment variables from a .env file into process.env.
The value of the environment variables are not loaded when we deploy the NodeJS into Azure AppService.
So, we need to add the environment variables into the AppService > Configuration and restart the app.

Stuck in loading with mongoose

I am trying to create a web-application with node.js, mongoose and MongoDB,
I am trying to load the web-page localhost:8800/api/auth/register which is stuck at loading since past 15 minutes.
VS Code Terminal return the following :
(node:2908) UnhandledPromiseRejectionWarning: MongooseError: Operation `users.insertOne()` buffering timed out after 10000ms
at Timeout.<anonymous> (E:\Projects\Applications\chitter-chatter\node_modules\mongoose\lib\drivers\node-mongodb-native\collection.js:185:20)
at listOnTimeout (internal/timers.js:554:17)
at processTimers (internal/timers.js:497:7)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:2908) 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: 3)
(node:2908) [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.
(node:2908) UnhandledPromiseRejectionWarning: MongooseError: Operation `users.insertOne()` buffering timed out after 10000ms
at Timeout.<anonymous> (E:\Projects\Applications\chitter-chatter\node_modules\mongoose\lib\drivers\node-mongodb-native\collection.js:185:20)
at listOnTimeout (internal/timers.js:554:17)
at processTimers (internal/timers.js:497:7)
(node:2908) 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: 4)
My Scripts are as following :
Index.js :
const application = express();
const mongoose = require("mongoose");
const dotenv = require("dotenv");
const helmet = require("helmet");
const morgan = require("morgan");
const userRoute = require("./routes/users");
const authRoute = require("./routes/auth");
dotenv.config();
mongoose.connect(process.env.MONGO_URL, {useNewUrlParser: true, useUnifiedTopology: true}, () => {
console.log("connected to MongoDB")
});
// middleware
application.use(express.json());
application.use(helmet());
application.use(morgan("common"));
application.use("/api/users", userRoute);
application.use("/api/auth", authRoute);
application.listen(8800, () => {
console.log("backend server is running!")
})
Auth.js :
const User = require("../models/User");
// REGISTER
router.get("/register", async (req, res) => {
const user = await new User ({
username: "john",
useremail: "john#gmail.com",
userpswrd: "123456"
})
await user.save();
res.send("oK")
});
module.exports = router
I am also using .env for MONGO VIA URL CONNECTION
Sorry for the bad writing apologies in advance also I am new to this so pls correct me! I know i have done a lot of mistakes,
Thanks for u're sincere time dedication and sympathy
First of all, you must make sure that you are connecting to the database without any error.
To do this, start listening on connect's callback function:
try {
// This configuration is better
mongoose.connect(process.env.MONGO_URL, {
useUnifiedTopology: true,
useNewUrlParser: true,
useCreateIndex: true,
useFindAndModify: false,
}, err => {
if (err) throw Error(err.message);
console.log("connected to MongoDB");
application.listen(8800, () => console.log("backend server is running!"));
});
} catch (error) {
console.log(error);
}
I think you should make this operation in a try-catch statement like this:
// REGISTER
router.get("/register", async (req, res) => {
try {
// Create user in database
const user = await User.create({
username: "john",
useremail: "john#gmail.com",
userpswrd: "123456"
});
res.status(200).json({ success: true });
} catch (error) {
res.status(500).json({ error });
console.log(error);
}
});
module.exports = router;
Then you can see error's details, and server keeps running.
If you can't solve the problem just add a comment here I'll be back ASAP
check your router or wifi if you are using to run mongoose
try with your mobile internet

Firebase Functions work in firebase deployment, but not locally

This code does not return any data in localhost, but works well when deployed in firebase. Any suggestions? (tried with both 'firebase emulators:start' & 'npm run serve').
I should get a json object containing courses.
I tried with try/catch without any result:
'npm run server' ("npm run build && firebase serve --only functions")
Error: Could not load the default credentials. Error: 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. 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()
'firebase emulators:start' -> no error, but an empty json: {"courses":[]}
Link to code: https://github.com/angular-university/firebase-course/blob/1-firebase-finished/functions/src/index.ts
import * as functions from 'firebase-functions';
import {db} from './init';
import * as express from "express";
const cors = require('cors');
const app = express();
app.use(cors({origin:true}));
app.get('/courses', async (request, response) => {
const snaps = await db.collection('courses').get();
const courses:any[] = [];
snaps.forEach(snap => courses.push(snap.data()));
response.status(200).json({courses});
});
export const getCourses = functions.https.onRequest(app);
_____________________________________________________________________________
init.ts
const admin = require('firebase-admin');
admin.initializeApp();
export const db = admin.firestore();
app.get('/courses', async (request, response) => {
try {
const snaps = await db.collection('courses').get();
const courses:any[] = [];
snaps.forEach((snap: any) => courses.push(snap.data()));
response.status(200).json({courses});
}
catch(err) {
console.error(err)
}
});
export const getCourses = functions.https.onRequest(app);
You need to provide the rights credentials. It works on google cloud because there are environment variables that make this automatically.
You need to set locally this environment variable with the path to your credentials file. Try this in your terminal:
export FIREBASE_CONFIG="/user/path/to/credential.json"
More info
Try following the documentation. It gives good examples on how to do this.

cannot set headers after they are sent to the client - mongoose

I want to write a small app that receives a welcome message via POST and returns it via GET. If I call only one method (GET or POST), there are no problems, but as soon as I call GET and POST, I get the following message:
events.js:174
throw er; // Unhandled 'error' event
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:470:11)
at ServerResponse.header (C:\Users\aph\IdeaProjects\hello-world-node\ExpressApp\node_modules\express\lib\response.js:767:10)
at ServerResponse.send (C:\Users\aph\IdeaProjects\hello-world-node\ExpressApp\node_modules\express\lib\response.js:170:12)
at Greeting.find (C:\Users\aph\IdeaProjects\hello-world-node\ExpressApp\routes\hello.js:16:13)
at C:\Users\aph\IdeaProjects\hello-world-node\node_modules\mongoose\lib\model.js:4568:16
at C:\Users\aph\IdeaProjects\hello-world-node\node_modules\mongoose\lib\query.js:4315:12
at process.nextTick (C:\Users\aph\IdeaProjects\hello-world-node\node_modules\mongoose\lib\helpers\query\completeMany.js:35:39)
at process._tickCallback (internal/process/next_tick.js:61:11)
Emitted 'error' event at:
at C:\Users\aph\IdeaProjects\hello-world-node\node_modules\mongoose\lib\model.js:4570:13
at C:\Users\aph\IdeaProjects\hello-world-node\node_modules\mongoose\lib\query.js:4315:12
at process.nextTick (C:\Users\aph\IdeaProjects\hello-world-node\node_modules\mongoose\lib\helpers\query\completeMany.js:35:39)
at process._tickCallback (internal/process/next_tick.js:61:11)
This is my code:
const express = require("express");
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const router = express.Router();
const Greeting = mongoose.model("Greeting", new Schema({message: String}));
router.get("/", (req, res) => {
Greeting.find({message: "Hello World!"}, (err, greetings) => {
if (err) {
console.log(err);
res.status(500).send(err);
return;
}
res.send(JSON.stringify(greetings));
});
res.send("There are no greetings!");
});
router.post('/', (req, res) => {
mongoose.connect("mongodb://localhost:27017/test", {useNewUrlParser: true});
new Greeting(req.body).save()
.then(() => {
res.send('success');
})
.catch(err => {
console.log(err);
res.status(500).send("Error: " + err)
});
});
module.exports = router;
I scanned this question but could not find a solution for my problem.
Greeting.find is an async function so the line res.send("There are no greetings!"); runs before the callback of Greeting.find runs which means the response 'There are no greetings!' is sent to the client before the callback ever runs.
Then in Greeting.find callback you're trying to send a response to the client again which causes the error.

Resources