POST request body is undefined using koa-body - javascript

Its my first time trying to do a POST request with Postman using Koa in my application. I have the router and the body parser but for some reason i still get an error message sayng that my request body is undefined. I think the body parser is not working but i have no idea why.
routes.js
const Koa = require('koa');
const bodyParser = require('koa-body')
const Router = require('koa-router')
const app = new Koa()
const router = new Router()
const Topic = require('./models/topic')
router.post('/topics', bodyParser(), async (ctx) => {
console.log(JSON.stringify(ctx.request.body))
const { name } = ctx.request.body
newPost = {
name: {name}
}
let newTopic = new Topic(newPost)
await newTopic.save(function(error, newPost){
if (error) {
console.log(error)
} else {
res.status(201).json({
message : 'Name added!'
}).send(newPost)
}
})
return
})
app
.use(router.allowedMethods())
.use(router.routes())
module.exports = router
topic.js
const mongoose = require('mongoose')
const Schema = mongoose.Schema
const TopicSchema = new Schema(
{
name: {type: String, required: true },
viewCount: {type: Number, default: 0 }
},
{
timestamps: true
}
)
module.exports = mongoose.model('two/Topic', TopicSchema)
Error message:
{}
Error: two/Topic validation failed: name: Cast to string failed for value "{ name: undefined }" at path "name"
at ValidationError.inspect (/home/node/app/node_modules/mongoose/lib/error/validation.js:47:26) ...
EDIT
Also adding in server.js for further reference
const Koa = require('koa');
const mongoose = require('mongoose');
const router = require('./routes');
const app = new Koa();
app.use(require('koa-body')());
app.use(router.routes());
mongoose.connect(process.env.MONGODB_URI, { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => {
const listener = app.listen(process.env.APP_PORT || 3000, () =>
console.log('App started on port ' + listener.address().port)
)
})
.catch((error) => {
console.log(error)
process.exit(1)
})
// app.proxy = true;
module.exports = app;

Related

when i change create request's path from "user" to "post" postman is returning html body and inside of it is text <pre>Cannot POST /api/posts</pre>

basically when i change "http://localhost:5000/api/users" to "http://localhost:5000/api/posts" in Create Request its giving me error if i leave it as it is which is "http://localhost:5000/api/users" if functions properly but for some damn reason postman is giving me this error which is shown in the picture and wont tell me whats causing it. anybody got any anwer? Error is described here
Cannot POST /api/posts
post.model.js
"
const {model, Schema } = require(`mongoose`)
const postSchema = new Schema (
{
user_id: {
type: Schema.Types.ObjectId,
ref: `User`,
required:true
},
title: {
type: String,
required: true
},
body: {
type: String,
required: true
}
},
{timestamps: true, versionKey: false}
)
module.exports = model('Post', postSchema);
"
post.controller.js
"
const Post = require(`../models/post.model`)
// #desc Get todos
// #route Get /api/todos
// #acsses Public
exports.getAll = async (request, response)=> {
const posts = await Post.find();
response.status(200).json({ sucsses: true, posts: posts})
}
// #desc Get todo
// #route GET /api/todo/:id
// #acsses Public
exports.getOne = async (request, response)=> {
const post = await Post.findById({ _id: request.params.id});
response.status(200).json({ sucsses: true, post: post})
}
// #desc Create todo
// #route POST /api/todo
// #acsses Public
exports.create = async (request, response)=> {
const post = await Post.create(request.body);
response.status(200).json({ sucsses: true, post: post})
}
// #desc Update todos
// #route Get /api/todos/:id
// #acsses Public
exports.updateOne = async (request, response)=> {
const post = await Post.findByIdAndUpdate(request.params.id, request.body, {new : true, runValidators: true})
response.status(200).json({ sucsses: true, post: post})
}
exports.deleteOne = async (request, response)=> {
const post = await Post.findByIdAndDelete(request.params.id)
response.status(200).json({ sucsses: true, post: post.id})
}
post.routes.js
"
const { Router } =require("express");
const { create, deleteOne, getAll, getOne, updateOne } = require("../controller/post.controller");
const router = Router()
router.route("/")
.get(getAll)
.post(create)
router.route("/:id")
.get(getOne)
.put(updateOne)
.delete(deleteOne)
module.exports = router;
server.js
"
const express = require("express")
const chalk = require("chalk")
const connectDatabase = require(`./api/config/connect.database`)
// =========== Aplication Routes =====
const user_routes = require("./api/routes/user.routes")
const todo_routes = require("./api/routes/todo.routes")
const post_routes = require("./api/routes/post.routes")
const comment_routes = require("./api/routes/comment.routes")
const album_routes = require("./api/routes/album.routes")
const photo_routes = require("./api/routes/photo.routes")
const app = express();
// Incoming Request body parser?======
app.use(express.json())
app.use(express.urlencoded({ extended: true}))
connectDatabase();
app.use(`/api/users`, user_routes)
app.use(`/api/todos`, todo_routes)
app.use(`/api/post`, post_routes)
app.use(`/api/comoment`, comment_routes)
app.use(`/api/album`, album_routes)
app.use(`/api/photo`, photo_routes)
const PORT = 5000
const SERVER_MODE = "development"
app.listen(PORT, ()=> {
console.log(chalk.bold.yellow(`Server running in ${SERVER_MODE} mode on port ${PORT}`));
})
connect.database.js
"
const mongoose = require("mongoose")
const chalk = require(`chalk`)
const connectDatabase = async ()=> {
const connect = await mongoose.connect("mongodb+srv://xynlep:123#project.41nkj.mongodb.net/members-api-reactional")
console.log(chalk.bold.cyan(`Mongo Connected: ${connect.connection.host}`))
}
module.exports = connectDatabase;
i tryed checking code if thers some mistake in it but everythings perfectly fine not 100% sure tho but since it doenst give me reason why it cant send create request i really couldn't try anything else but google

Cannot POST /api/sentiment

I'm testing the endpoint for /api/sentiment in postman and I'm not sure why I am getting the cannot POST error. I believe I'm passing the correct routes and the server is listening on port 8080. All the other endpoints run with no issue so I'm unsure what is causing the error here.
server.js file
const express = require("express");
const cors = require("cors");
const dbConfig = require("./app/config/db.config");
const app = express();
var corsOptions = {
origin: "http://localhost:8081"
};
app.use(cors(corsOptions));
// parse requests of content-type - application/json
app.use(express.json());
// parse requests of content-type - application/x-www-form-urlencoded
app.use(express.urlencoded({ extended: true }));
const db = require("./app/models");
const Role = db.role;
db.mongoose
.connect(`mongodb+srv://tami00:MEUxClWqUNbLz359#cluster0.gmvao.mongodb.net/test?retryWrites=true&w=majority`, {
useNewUrlParser: true,
useUnifiedTopology: true
})
.then(() => {
console.log("Successfully connect to MongoDB.");
initial();
})
.catch(err => {
console.error("Connection error", err);
process.exit();
});
// simple route
app.use('/api/favourite', require('./app/routes/favourite.routes'));
app.use('/api/review', require('./app/routes/review.routes'));
app.use('/api/sentiment', require('./app/routes/sentiment-analysis.routes'));
// routes
// require(".app/routes/favourite.routes")(app);
require("./app/routes/auth.routes")(app);
require("./app/routes/user.routes")(app);
// set port, listen for requests
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}.`);
});
function initial() {
Role.estimatedDocumentCount((err, count) => {
if (!err && count === 0) {
new Role({
name: "user"
}).save(err => {
if (err) {
console.log("error", err);
}
console.log("added 'user' to roles collection");
});
new Role({
name: "creator"
}).save(err => {
if (err) {
console.log("error", err);
}
console.log("added 'creator' to roles collection");
});
new Role({
name: "watcher"
}).save(err => {
if (err) {
console.log("error", err);
}
console.log("added 'watcher' to roles collection");
});
}
});
}
sentiment-analysis routes file
const express = require('express');
const router = express.Router();
const getSentiment = require('../sentiment-analysis/sentimentAnalysis')
router.post('/api/sentiment', (req, res) => {
const data = req.body.data
const sentiment = getSentiment(data)
return res.send({sentiment})
})
module.exports = router;
sentimentAnalysis.js file
const aposToLexForm = require("apos-to-lex-form");
const {WordTokenizer, SentimentAnalyzer, PorterStemmer} = require("natural");
const SpellCorrector = require("spelling-corrector");
const stopword = require("stopword");
const tokenizer = new WordTokenizer();
const spellCorrector = new SpellCorrector();
spellCorrector.loadDictionary();
const analyzer = new SentimentAnalyzer('English', PorterStemmer, 'afinn')
function getSentiment(text){
if(!text.trim()) {
return 0;
}
const lexed = aposToLexForm(text).toLowerCase().replace(/[^a-zA-Z\s]+/g, "");
const tokenized = tokenizer.tokenize(lexed)
const correctSpelling = tokenized.map((word) => spellCorrector.correct(word))
const stopWordsRemoved = stopword.removeStopwords(correctSpelling)
console.log(stopWordsRemoved)
const analyzed = analyzer.getSentiment(stopWordsRemoved);
console.log(analyzed)
}
module.exports = getSentiment;
console.log(getSentiment("Wow this is fantaztic!"))
console.log(getSentiment("let's go together?"))
console.log(getSentiment("this is so bad, I hate it, it sucks!"))
I see that you use your routes like: app.use('/api/sentiment', require('./app/routes/sentiment-analysis.routes'));. But then in your sentiment-analysis you again use /api/sentiment so your request URL should be /api/sentiment/api/sentiment
Shouldn't it be:
const data = req.body.data

MongoDb updating references

please i need help with creating the update function in the assignmentsController, i want to be able to have a user create an assignment, then i can be able to create a quiz inside of the assignments and return it. for example this is what i want return after updating the assignment quiz section.
{ "quiz": [{question:""this is a sample question?", "correct_answer":"sample correct", "incorrect_answers: ["wrong", "not correct"], "createdAt": "2020-12-10T00:50:27.932Z", "_id": "5fd170d6712a647ad072c449", "title": "what are you?", }
This is the update function
export const updateAssignments = async (req, res) => {
const { id } = req.params;
const {title} = req.body;
if (!mongoose.Types.ObjectId.isValid(id)) return res.status(404).send(`No Asssignment with id: ${id}`);
const updatedPost = {title,_id: id, $push: { quiz:[{$each: updatedquiz} ]}};
// await Assignment.findByIdAndUpdate(assignmentId)
await Assignments.findByIdAndUpdate(id, updatedPost, { new: true });
res.json(updatedPost);
}
these are all the files
**Assignment.js**
import mongoose from 'mongoose'
const AssignmentsSchema = new mongoose.Schema({
title: String,
quiz: [{
type: mongoose.Schema.Types.ObjectId,
ref: "Quiz"
}],
createdAt: {
type: Date,
default: new Date(),
},
});
const Assignments = mongoose.model("Assignments", AssignmentsSchema)
export default Assignments;
`
- **Quiz.js**
import mongoose from 'mongoose';
const QuizSchema = mongoose.Schema({
question: String,
correct_answer: String,
incorrect_answers: [],
assignments: {
type: mongoose.Schema.Types.ObjectId,
ref: "Assignments"
},
})
var Quiz = mongoose.model('Quiz', QuizSchema);
export default Quiz;
**AssignmentsController.js**
import express from 'express';
import mongoose from 'mongoose';
import Assignments from '../models/Assignments.js';
import Assignment from '../models/Quiz.js';
const router = express.Router();
export const getAssignments = async (req, res) => {
try {
const postAssignment = await Assignments.find().populate('quiz');
res.status(200).json(postAssignment);
} catch (error) {
res.status(404).json({ message: error.message });
}
}
export const getAssignmentsById = async (req, res) => {
const { id } = req.params.id;
try {
const post = await (await Assignments.findById(id)).populate('quiz');
res.status(200).json(post);
} catch (error) {
res.status(404).json({ message: error.message });
}
}
export const createAssignments = async (req, res) => {
try {
const { title, createdAt} = req.body;
const newAssignment = new Assignments({
title,
createdAt,
quiz: [req._id],
});
await newAssignment
.populate('quiz')
.execPopulate()
// newAssignment.assignmentQuestion = newAssignment.assignment.question
// newAssignment.assignmentDate = createdAt
// newAssignment.correctanswer = registration.user.email
newAssignment.save()
res.status(201).json(newAssignment );
} catch (error) {
res.status(409).json({ message: 'does not work' });
}
}
export const updateAssignments = async (req, res) => {
const { id } = req.params;
// const { quizid } = req.params;
// const { question, correct_answer, incorrect_answers} = req.body;
const {title} = req.body;
if (!mongoose.Types.ObjectId.isValid(id)) return res.status(404).send(`No Asssignment with id: ${id}`);
const updatedPost = {title,_id: id, $push: { quiz:[{$each: updatedquiz} ]}};
// await Assignment.findByIdAndUpdate(assignmentId)
await Assignments.findByIdAndUpdate(id, updatedPost, { new: true });
res.json(updatedPost);
}
export const deleteAssignment = async (req, res) => {
const { id } = req.params;
if (!mongoose.Types.ObjectId.isValid(id)) return res.status(404).send(`No Assignment with id: ${id}`);
await Assignment.findByIdAndRemove(id);
res.json({ message: "Assignment deleted successfully." });
}
export default router;
**assignmentsRoute.js**
import express from 'express';
import { createAssignments, getAssignments, getAssignmentsById, updateAssignments } from '../controllers/AssignmentsController.js';
const router = express.Router();
//Assignment
router.get('/', getAssignments);
router.post('/', createAssignments);
router.get('/:assignment_id', getAssignmentsById);
router.patch('/:assignment_id/quiz', updateAssignments);
router.delete('/:assignment_id', deleteAssignment);
export default router;
**server.js**
import express from 'express'
import bodyParser from 'body-parser'
import mongoose from 'mongoose'
import cors from 'cors'
import dotenv from 'dotenv'
import userRoutes from './routes/userRoute.js';
import quizRoutes from './routes/quizRoute.js'
import assignmentsRoutes from './routes/assignmentsRoute.js';
import loginRoutes from './routes/loginRoute.js';
import registrationRoutes from './routes/registrationRoute.js';
const app = express();
app.use(cors());
const PORT = process.env.PORT || 8001;
if(process.env.NODE_ENV !== 'production'){
dotenv.config()
}
app.use(bodyParser.json()) // for parsing application/json
app.use(bodyParser.urlencoded({ extended: true }))
app.use('/user', userRoutes);
app.use('/login', loginRoutes);
app.use('/registration', registrationRoutes);
app.use('/quiz', quizRoutes);
app.use('/assignments', assignmentsRoutes);
mongoose.connect(process.env.MONGO_DB_CONNECTION, { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => app.listen(PORT, () => console.log(`Server Running on Port: http://localhost:${PORT}`)))
.catch((error) => console.log(`${error} did not connect`));
what i initially wanted was to create an assignment and then add quiz questions in it, in order to do that i needed to change the model schema of the Assignment model to have an array of quizzes instead of it referencing a model of Quiz. then i performed the $push method and so i can add as many questions as i want.
Assignments.js
import mongoose from 'mongoose'
const AssignmentsSchema = new mongoose.Schema({
title: String,
quizes: [{
question:String,
correct_answer:String,
incorrect_answers:[]
}],
createdAt: {
type: Date,
default: new Date(),
},
});
const Assignments = mongoose.model("Assignments", AssignmentsSchema)
export default Assignments;
then i created the addQuestion function in AssignmentController.js
`export const addQuestion = async (req, res) =>{
const { id } = req.params;
try {
const addedQuestion = await Assignments.findByIdAndUpdate(
{_id: id},
{ $push: { quizes: {$each: req.body.quizes}}},
{safe: true, upsert: true, new : true}
);`
this is the result
{
_id:5fd83417c78f8dd70351c613
createdAt:2020-12-15T03:53:17.724+00:00
title:"first assignment"
quizes:Array
{0:Object
incorrect_answers:Array
{
0:"wrong"
1:"write"
2:"ugly"
}
_id:5fd83593106af1d8fa87b94c
question:"this is question 1"
correct_answer:"sample answer"
{
1:Object
incorrect_answers:Array
_id:5fd835a3106af1d8fa87b94d
question:"this is question 2"
correct_answer:"sample answer 2"
{
2:Object
incorrect_answers:Array
_id:5fd835ba106af1d8fa87b94e
question:"this is question 3"
correct_answer:"sample answer 3"
}
}
}

Express-winston middleware error on GET and POST request to mongoDB

I have the following structure:
logger.js:
const logger = module.exports = require('winston')
logger.add(new logger.transports.File(
{
name: 'debug-file',
filename: 'log.log',
level: 'debug',
handleExceptions: true,
humanReadableUnhandledException: true,
exitOnError: true,
json: false,
maxsize: 104857600,
maxfiles: 5
}))
logger.add(new logger.transports.Console(
{
name: 'error-console',
level: 'error',
handleExceptions: true,
humanReadableUnhandledException: true,
exitOnError: true
}))
server.js:
const port = process.env.PORT || 5000;
const logger = require('./logger.js')
const database = require('./database/createDatabase.js')({ logger })
const app = require('./app/createExpressApp.js')
const server = require('http').createServer()
server
.on('request', app)
.on('listening', function() {
const addr = this.address()
const bind = typeof addr === 'string' ? `pipe ${addr}` : `port ${addr.port}`
logger.info(`Listening on ${bind}`)
})
.on('error', function(error) {
if (error.syscall !== 'listen') throw error
const addr = this.address() || { port }
const bind = typeof addr === 'string' ? `pipe ${addr}` : `port ${addr.port}`
switch (error.code) {
case 'EACCES':
logger.error(`${bind} requires elevated privileges`)
process.exit(1)
case 'EADDRINUSE':
logger.error(`${bind} is already in use`)
process.exit(1)
default:
throw error
}
})
.listen(port)
createDatabase.js:
const mongoose = require('mongoose')
const glob = require('glob')
const path = require('path')
module.exports = ({ logger }) => {
const url = process.env.ATLAS_URI
|| "mongodb+srv://(removed for stackoverflow question)"
mongoose.connect(url)
const db = glob.sync('./schemas/**/*.js', { cwd: __dirname })
.map(filename => {
return {
schema: require(filename),
name: path
.basename(filename)
.replace(path.extname(filename), ''),
}
})
.map(({name, schema}) => mongoose.model(name, schema))
.reduce((db, model) => {
return {
...db,
[model.modelName]: model,
}
}, {})
mongoose
.connection
.on('error', error => {
throw error
})
.once('open', () => logger.info(`MongoDB connection established successfully!`) &&
console.log(`MongoDB connection established successfully!`))
return db
}
and finally getUsers.js:
const Router = require('express').Router
// export to router
module.exports = Router({mergeParams: true})
.get('/v1/users', async (req, res, next) => {
try {
const users = await req.db.User.find()
res.send(users)
}
catch (error) {
next(error)
}
})
I have triple checked folder structure, syntax and everything else I can think of, but think I lack understanding of winston. I get the following error when I go to perform GET request for Users:
{"error":{},"level":"error","message":"uncaughtException: transports or a winstonInstance are required by express-winston middleware
I have a feeling its a rudimentary error and I'm missing something simple. Anyone have ideas on what would be causing the error?
This is because your logger, and database are not imported into your server.js
Change your server.js imports from
const port = process.env.PORT || 5000;
const logger = require('./logger.js')
const database = require('./database/createDatabase.js')({ logger })
const app = require('./app/createExpressApp.js')
const server = require('http').createServer()
to
const port = process.env.PORT || 5000;
const logger = require('./logger.js')
const database = require('./database/createDatabase.js')({ logger })
const app = require('./app/createExpressApp.js')({ logger, database });
const server = require('http').createServer()
both, database and the Winston logger are exported, however, they are not being pushed to the createExpressApp.js, which is needed and will remove this error and log the requests from postman/server properly in your log file.
This is an error from express-winston, which requires the winstonInstance to not be null. I bet if you try to console.log(logger) in your createExpressApp.js it will come back undefined.
Per the express-winston documentation: https://www.npmjs.com/package/express-winston
PS. Ensure you add:
mongoose.connect(url, {
useNewUrlParser: true,
useCreateIndex: true,
useFindAndModify: false,
useUnifiedTopology: true,
});
these methods to your mongoDB URL, or your will get depreciation warnings :D

node js updating post request body

I am sending request from form (using Angularjs) to create new user. It works and inserts data in my collection. But how i manage to update my data on backend part using node js express. For example i want to check if username is free. I am trying to console.log something when i send post request. But nothing is logging.
Here is my server.js
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const restify = require('express-restify-mongoose');
//const userRep = require('./front/core/repository/user/user.repository');
// Middleware
const head = require('./back/midleware/headers.config');
// Models
// TODO provide schema when it will be raedy
const userModel = require('./back/models/user.model');
const app = express();
const router = express.Router();
mongoose.Promise = global.Promise;
mongoose.connect('mongodb://localhost/users');
// Body parser config
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// Headers config
app.use(head.headerConfig);
// Endpoint configuration
restify.serve(router, userModel.UserModel, {
name: 'users',
});
app.use(router);
app.post('/users', (req, res) => {
console.log('req.post')
})
app.post('/users', (req, res) => {
console.log('req.post')
})
app.listen(2000, function () {
console.info('Server is locating on port 2000');
console.info('to access localhost:2000/api/v1');
});
Ajax Request:
import { UserRepository } from '../../core/repository/user/user.repository';
import * as _ from 'lodash';
class HttpExampleController {
constructor(UserRepository) {
this.repository = UserRepository;
this.allUsers = [];
this.user = {};
this.newUser = {
id: 4,
email: "new#email.com",
username: "newUserName",
name: "newName"
};
this.updatedUser = {
email: "updated#email.com",
name: "updatedUserName"
};
this.getAllUsers();
}
getAllUsers() {
this.repository.getAllUsers()
.then(userList => {
this.allUsers = userList;
});
}
// Discuss if we need this method
getUser(userId) {
this.repository.getUser(userId)
.then(user => {
this.user = user;
});
}
createUser(user) {
this.repository.createUser(user)
.then(res => {
this.allUsers.push(res);
});
}
updateUser(user, data) {
let index = _.indexOf(this.allUsers, _.find(this.allUsers, findUser => findUser._id === user._id));
this.repository.updateUser(user._id, data)
.then(res => {
this.allUsers[index] = res;
});
}
deleteUser(user) {
let index = _.indexOf(this.allUsers, _.find(this.allUsers, findUser => findUser._id === user._id));
this.repository.deleteItem(user._id)
.then(res => _.pull(this.allUsers, res));
}
testFunc() {
this.allUsers.shift();
}
}
export { HttpExampleController };

Categories