I have been googling, searching on stack and been trying to solve this for a while now.
None of the posted solutions seem to help.
Server runs smoothly in VSC (if I input wrong pass, it gives authentication error.
Seemingly, it connects fine).
Tried with Compass and it connects fine there too.
Posting this in Postman [RAW > JSON/Application]:
{
"name": "Harry Potter",
"price": "12.99"
}
Returns this in VSC:
POST /products - - ms - -
And an error message in Postman: Error: read ECONNRESET
I am following a RESTful API series on youtube.
I am a bit confused as to where the problem lies then. Any ideas?
Any help would be greatly appreciated. Thanks in advance!
server.js
const http = require('http');
const app = require('./app');
const port = process.env.PORT || 3000;
const server = http.createServer(app);
server.listen(port);
app.js
const express = require('express');
const app = express();
const morgan = require('morgan');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
// Set route for product and order
const productRoutes = require('./api/routes/products');
const orderRoutes = require('./api/routes/orders');
mongoose.connect(
'mongodb://testDB:' +
process.env.MONGO_ATLAS_PW +
'#node-rest-shop-shard-00-00.e0tzo.mongodb.net:27017,node-rest-shop-shard-00-01.e0tzo.mongodb.net:27017,node-rest-shop-shard-00-02.e0tzo.mongodb.net:27017/test?ssl=true&replicaSet=atlas-be641c-shard-0&authSource=admin&retryWrites=true&w=majority',
{
useNewUrlParser: true,
useUnifiedTopology: true
}
);
app.use(morgan('dev'));
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Header', 'Origin, X-Requested-Width, Content-Type, Accept, Authorization');
if (req.method === 'OPTIONS') {
res.header('Access-Control-Allow-Methods', 'PUT, POST, PATCH, DELETE, GET');
return res.status(200).json({});
}
});
// Routes which handles
app.use('/products', productRoutes);
app.use('/orders', orderRoutes);
app.use((req, res, next) => {
const error = new Error('Not found');
error.status = 404;
next(error);
})
app.use((error, req, res, next) => {
res.status(error.status || 500);
res.json({
error: {
message: error.message
}
});
});
module.exports = app;
models/product.js
const mongoose = require('mongoose');
const productSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectID,
name: String,
price: Number
});
module.exports = mongoose.model('Product', productSchema);
routes/orders.js
const express = require('express');
const router = express.Router();
router.get('/', (req, res, next) => {
res.status(200).json({
message: 'Orders were fetched'
});
});
router.post('/', (req, res, next) => {
const order = {
productId: req.body.productId,
quantity: req.body.quantity
};
res.status(201).json({
message: 'Order was created',
orders: order
});
});
router.get('/:orderId', (req, res, next) => {
res.status(200).json({
message: 'Order details',
orderId: req.params.orderId
});
});
router.delete('/:orderId', (req, res, next) => {
res.status(200).json({
message: 'Order deleted',
orderId: req.params.orderId
});
});
module.exports = router;
routes/products.js
const express = require('express');
const router = express.Router();
const mongoose = require('mongoose');
const Product = require('../models/product');
router.get('/', (req, res, next) => {
res.status(200).json({
message: 'handling GET requests to /products'
});
});
router.post('/', (req, res, next) => {
const product = new Product({
_id: new mongoose.Types.ObjectId(),
name: req.body.name,
price: req.body.price
});
product.save().then(result => {
console.log(result);
})
.catch(err => console.log(err));
res.status(201).json({
message: 'handling POST requests to /products',
createProduct: product
});
});
router.get('/:productId', (req, res, next) => {
const id = req.params.productId;
if (id === 'special') {
res.status(200).json({
mesage: 'Special ID discovered',
id: id
});
} else {
res.status(200).json({
message: 'You passed an ID',
id: id
});
}
});
router.patch('/:productId', (req, res, next) => {
res.status(200).json({
message: 'Updated product!'
});
});
router.delete('/:productId', (req, res, next) => {
res.status(200).json({
message: 'Deleted product!'
});
});
module.exports = router;
nodemon.json
{
"env": {
"MONGO_ATLAS_PW": "<user password here - removed for post>"
}
}
Related
Im writing my expressJs application, and Im finding in my routes controller the same duplicated code for catching exception, I was wondering how to avoid this.
I have checked this thread, but I get this error "Cannot read property 'catch' of undefined" : Express Try and Catch in Form of middleware
this is my route.js
const express = require("express");
const createHttpError = require("http-errors");
const Validator = require("../middlewares/Validator");
const TaskNotFoundException = require("../services/TaskNotFoundException");
const TaskService = require("../services/TaskService");
router.get("/tasks", async (req, res, next) => {
try {
const data = await TaskService.getTasks();
res.send({ code: 200, message: "Success", data });
} catch (error) {
next(createHttpError(500));
}
});
router.get("/task/:id", async (req, res, next) => {
const { id } = req.params;
try {
const data = await TaskService.getTask(id);
res.send({ code: 200, message: "Success", data });
} catch (error) {
if (error instanceof TaskNotFoundException) {
next(createHttpError(404));
} else {
next(createHttpError(500));
}
}
});
and the list goes on
as you see in all my routes I have a try catch block with the possible errors (either only a 500, or a 500/404). And I would like to avoid this repetition.
this is my app.js
const express = require("express");
const bodyParser = require("body-parser");
const createHttpError = require("http-errors");
const api = require("./routes/api");
const app = express();
app.use(express.json());
app.use(bodyParser.json());
app.use("/api", api);
// Catch HTTP 404
app.use((req, res, next) => {
next(createHttpError(404));
});
// Error Handler
app.use((err, req, res, next) => {
res.status(err.status || 500);
res.json({
error: {
status: err.status || 500,
message: err.message,
},
});
});
module.exports = app;
Like I said, it works perfectly now, I would just like to try to avoid the try catch code duplication, and Ive checked the other questions in Stackoverflow but havent helped. The solution ive linked returns a 500 with this catch undefined message (which is not what I want) and on other routes that also have a 404 it just doesnt work.
Thanks a lot!
Update:
I followed Heikos advice but still not working
api.js
const express = require("express");
const createHttpError = require("http-errors");
const Validator = require("../middlewares/Validator");
const TaskNotFoundException = require("../services/TaskNotFoundException");
const TaskService = require("../services/TaskService");
const router = express.Router();
router.get("/tasks", async (req, res, next) => {
const data = await TaskService.getTasks();
res.send({ code: 200, message: "Success", data });
});
app.js
const express = require("express");
const bodyParser = require("body-parser");
const createHttpError = require("http-errors");
const api = require("./routes/api");
const app = express();
app.use(express.json());
app.use(bodyParser.json());
app.use("/api", api);
function catchAsyncErrors(middleware) {
return async function(req, res, next) {
try {
await middleware(req, res, next);
} catch(err) {
next(err);
}
};
}
// Catch HTTP 404
app.use(catchAsyncErrors((req, res, next) => {
next(createHttpError(404));
}));
// Error Handler
app.use(catchAsyncErrors((err, req, res, next) => {
res.status(err.status || 500);
res.json({
error: {
status: err.status || 500,
message: err.message,
},
});
}));
module.exports = app;
If the code inside your async middleware functions contains an await, you must also wrap it in a try-catch block, otherwise a rejected promise will be unhandled. For example:
app.use(async function(req, res, next) {
try {
await Promise.reject("error");
} catch(err) {
next(err);
}
});
propagates the error to the error handler, but without the try-catch block it leads to an "UnhandledPromiseRejection".
You can save some typing if you wrap your middleware into a catchAsyncErrors function:
function catchAsyncErrors(middleware) {
return async function(req, res, next) {
try {
await middleware(req, res, next);
} catch(err) {
next(err);
}
};
}
router.get("/tasks", catchAsyncErrors(async (req, res, next) => {
const data = await TaskService.getTasks();
res.send({ code: 200, message: "Success", data });
}));
So when I try to make a new post, and then delete it without reloading the page, I can't and I get this error. I'm new to mongodb and this is my all first app MEAN-like
This is my code:
const express = require("express");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const Post = require("../models/post");
const app = express();
mongoose
.connect(
"mongodb+srv://Milos:re0zygTSPZjXGpAB#cluster0.ijb8l.mongodb.net/myFirstDatabase?retryWrites=true&w=majority",
{ useNewUrlParser: true, useUnifiedTopology: true }
)
.then(() => {
console.log("Connected to database!");
})
.catch(() => {
console.log("Connection failed!");
});
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept"
);
res.setHeader(
"Access-Control-Allow-Methods",
"GET, POST, PATCH, DELETE, OPTIONS"
);
next();
});
app.post("/api/posts", (req, res, next) => {
const post = new Post({
title: req.body.title,
content: req.body.content,
});
post.save();
res.status(201).json({
message: "Post added successfully",
});
});
app.get("/api/posts", (req, res, next) => {
Post.find().then((documents) => {
console.log(documents);
res.status(200).json({
message: "Posts fetched successfully!",
posts: documents,
});
});
});
app.delete("/api/posts/:id", (req, res, next) => {
Post.deleteOne({ _id: req.params.id }).then((result) => {
console.log(result);
res.status(200).json({ message: "Post deleted!" });
});
});
module.exports = app;
And here is my deletePost function
deletePost(postId: string) {
this.http
.delete('http://localhost:3000/api/posts/' + postId)
.subscribe(() => {
const updatedPosts = this.posts.filter(post => post.id !== postId);
this.posts = updatedPosts;
this.postsUpdated.next([...this.posts]);
});
}
I get that error and when I reload the page it all works fine. But I don't need a page reload, I need it all to work in real time.
This is because mongoose try to cast id value to Object(_id) field so that it can properly query for the matching doc. This is an ObjectId but "null" is not a valid ObjectId so the cast fails.
// the id here is null, try passing valid id and it will
// delete the specific doc
//Also, use catch blocks to catch errors after all thens
// or create a global handler for it
app.delete("/api/posts/:id", (req, res, next) => {
Post.deleteOne({ _id: req.params.id }).then((result) => {
console.log(result);
res.status(200).json({ message: "Post deleted!" });
}).catch(console.error);
});
I am receiving an authenticate.getToken is not a function error.
var express = require('express');
const bodyParser = require('body-parser');
var User = require('../models/user');
const passport = require('passport');
var authenticate = require('../authenticate');
var router = express.Router();
router.use(bodyParser.json());
/* GET users listing. */
router.get('/', function (req, res, next) {
res.send('respond with a resource');
});
router.post('/signup', (req, res, next) => {
User.register(
new User({ username: req.body.username }),
req.body.password, (err, user) => {
if (err) {
res.statusCode = 500;
res.setHeader('Content-Type', 'application/json');
res.json({ err: err });
} else {
passport.authenticate('local')(req, res, () => {
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
res.json({ success: true, status: 'Registration Successful!' });
});
}
}
);
});
router.post('/login', passport.authenticate('local'), (req, res) => {
var token = authenticate.getToken({ _id: req.user._id });
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
res.json({ success: true, token: token, status: 'You are successfully logged in!' });
});
router.get('/logout', (req, res) => {
if (req.session) { req.session.destroy();
res.clearCookie('session-id');
res.redirect('/');
} else {
var err = new Error('you are not logged in');
err.status = 403;
next(err);
}
});
module.exports = router;
The error simply means that authenticate.getToken is not a function. have you exported correctly in your authenticate.js file? It may be worth posting your authenticate.js file to your OP.
It should look something like this for it to work:
authenticate.js
module.exports = {
getToken: function() {
// code here
}
}
On localhost:5000/posts my data is successfully showing but if I do the same thing in Heroku: https://rest-in-peep.herokuapp.com/posts I get an application error. https://rest-in-peep.herokuapp.com/ works fine and I deployed it through Heroku GIT. I made sure to config my environmental vars in Heroku and added a Procfile but I am still getting this application error. I've been trying all day to figure this out but what I expect to happen is if I type in https://rest-in-peep.herokuapp.com/posts, I will get all the data that is being stored on my MongoDB database.
app.js file
const http = require("http");
const express = require("express");
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const cors = require("cors");
require("dotenv/config");
const app = express();
const server = http.createServer(app);
//Middlewares
app.use(cors());
app.use(bodyParser.json());
//Import Routes
const postsRoute = require("./routes/posts");
app.use("/posts", postsRoute);
//ROUTES
app.get("/", (req, res) => {
res.send("We are on home");
});
//Connect to DB
mongoose.connect(
process.env.DB_CONNECTION,
{ useNewUrlParser: true },
() => console.log("connected to MongoDB")
);
//How do we start listening to the server
server.listen(process.env.PORT || 5000, () => {
console.log("App now running on PORT");
});
routes>
posts.js
const express = require("express");
const Post = require("../models/Posts");
const router = express.Router();
//GETS BACK ALL THE POSTS
router.get("/", async (req, res) => {
try {
const posts = await Post.find();
res.json(posts);
} catch (err) {
res.json({ message: err });
}
});
//SUBMITS A POST
router.post("/", async (req, res) => {
console.log(req);
const post = new Post({
quote: req.body.quote
});
try {
const savedPost = await post.save();
res.json(savedPost);
} catch (err) {
res.json({ message: err });
}
});
//SPECIFIC POST
router.get("/:postId", async (req, res) => {
try {
const post = await Post.findById(req.params.postId);
res.json(post);
} catch (err) {
res.json({ message: err });
}
});
//Delete Post
router.delete("/:postId", async (req, res) => {
try {
const removedPost = await Post.remove({ _id: req.params.postId });
res.json(removedPost);
} catch (err) {
res.json({ message: err });
}
});
//Update a post
router.patch("/:postId", async (req, res) => {
try {
const updatedPost = await Post.updateOne(
{ _id: req.params.postId },
{
$set: { quote: req.body.quote }
}
);
res.json(updatedPost);
} catch (err) {
res.json({ message: err });
}
});
module.exports = router;
gitignore
/node_modules
models>Posts.js
const mongoose = require("mongoose");
const PostSchema = mongoose.Schema({
quote: {
type: String,
required: true
}
});
module.exports = mongoose.model("Posts", PostSchema);
MEAN Stack
I keep getting
TypeError: Cannot read property 'first_name' of undefined
when trying to execute this code (all variables, including modules are defined in other parts of the code). While using GET Method, my code is working fine. But for POST Method, it throws error. Attached the screenshot below.
Advance Rest Client POST Method Exception
Added my code below.
Thanks in advance
//app.js
//Importing Modules
var express = require('express');
var mongoose = require('mongoose');
var bodyparser = require('body-parser');
var cors = require('cors');
var path = require('path');
var app = express();
//port Number
const port = 3000;
const route = require('./routes/route');
//Connect to MongoDB
mongoose.connect('mongodb://localhost:27017/contactlist');
//if connected
mongoose.connection.on('connected', () => {
console.log("Mongo DB Connected successfully");
});
//if not connected
mongoose.connection.on('error', (err) => {
if (err) {
console.log('Error in connecting to the MongoDB');
}
});
//adding middleware cors
app.use(cors());
//routes will happen here
app.use('/api', route);
//adding middleware
app.use(bodyparser.json());
//Static files
app.use(express.static(path.join(__dirname, 'public')));
//Testing
app.get('/', (req, res) => {
res.send("Hello Vinoth");
});
app.get('/yahoo', (req, res) => {
res.send("Hello Vinoth");
});
//Connection
app.listen(port, () => {
console.log("Server started at port:" + port);
});
//route.js
const express = require('express');
const router = express.Router();
const Contact = require('../models/contacts');
// retrieving details
router.get('/contacts', (req, res, next) => {
Contact.find(function(err, contacts) {
res.json(contacts);
});
});
// Add Contacts
//Add contact
router.post('/contact', (res, req, next) => {
console.log('Insides');
let newContact = new Contact({
first_name: req.body.first_name,
last_name: req.body.last_name,
phone: req.body.phone
});
newContact.save((err, contact) => {
if (err) {
res.json({
msg: 'Failed to add contact'
});
} else {
res.json({
msg: 'Contact added successfully'
});
}
});
});
// Delete Contacts
router.delete('/contact/:id', (req, res, next) => {
Contact.remove({
_id: req.params.id
}, function(err, result) {
if (err) {
res.json(err);
} else {
res.json(result);
}
});
});
module.exports = router;
//contacts.js
const mongoose = require('mongoose');
const ContactSchema = mongoose.Schema({
first_name: {
type: String,
required: true
},
last_name: {
type: String,
required: true
},
phone: {
type: String,
required: true
}
});
const Contact = module.exports = mongoose.model('Contact', ContactSchema);
Try moving app.use(bodyparser.json()) before app.use('/api', route). Hope this helps.
First of all you need to Declare
//adding middleware
app.use(bodyparser.json());
Before use all routes. So you need to update your app.js like:
//adding middleware
app.use(bodyparser.json());
//routes will happen here
app.use('/api', route);
In additional you need to refactor your route.js
code like this:
//Add contact
router.post('/contact', (res, req, next) => {
const {
first_name,
last_name,
phone
} = req.body;
let newContact = new Contact({
first_name,
last_name,
phone
});
newContact.save((err, contact) => {
if (err) {
res.json({
msg: 'Failed to add contact'
});
} else {
res.json({
msg: 'Contact added successfully'
});
}
});
});