How to fix MongoDB documents being just id and __v - node.js

When I try to add a post to the database the JSON Body is perfectly fine, but when I retrieve these it only shows id and __v (versionKey)
I've tried using body-parser in different ways, such as...
app.use('bodyParser.json()')
var urlencodedParser = bodyParser.urlencoded({ extended: false })
var jsonParser = bodyParser.json();
The last two included in the app.post method.
This is my index.js
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const mongoose = require('mongoose');
const app = express();
const port = 4000;
const postRoutes = express.Router();
let Post = require('./post.model');
var urlencodedParser = bodyParser.urlencoded({ extended: false })
var jsonParser = bodyParser.json();
app.use(cors());
app.use('/', express.static('public'));
app.use(bodyParser.json());
app.use('/posts', postRoutes);
mongoose.connect("mongodb://127.0.0.1:27017/mern-blog-test", { useNewUrlParser: true });
const connection = mongoose.connection;
connection.once('open', function() {
console.log('Succesfully established connection to MongoDB Database');
})
postRoutes.route('/').get(function (req, res) {
Post.find(function (err, posts) {
if (err) {
console.log(err);
} else {
res.json(posts);
}
});
});
postRoutes.route(':id').get(function(req,res) {
let id = req.params.id;
Post.findById(id, function(err, post) {
res.json(post);
});
});
// todoRoutes.route('/add').post(function (req, res) {
// let todo = new Todo(req.body);
// todo.save()
// .then(todo => {
// res.status(200).json({ 'todo': 'todo added successfully' });
// })
// .catch(err => {
// res.status(400).send('adding new todo failed');
// });
// });
app.get('/create', function(req,res){
res.sendFile(__dirname + '/public/add.html');
})
app.post('/makepost', urlencodedParser, function(req,res) {
console.log(req.body);
let post = new Post(req.body);
post.save()
.then(todo => {
res.sendFile(__dirname + '/public/add.html')
})
.catch(err => {
res.status(400).send('adding new post failed!');
});
});
This is my form
<label for="title">Title</label>
<input type="text" name="title">
<label for="category">Category</label>
<select name="category">
<option>Coding</option>
<option>Music</option>
<option>Books</option>
<option>Other Stuff</option>
</select>
<label for="content">Content</label>
<input type="text" name="content">
<input type="submit">
</form>
And my post.model.js
const Schema = mongoose.Schema;
let Post = new Schema({
post_title: {
type: String
},
post_date: {
type: Date
},
post_shortdesc: {
type: String
},
post_content: {
type: String
}
});
module.exports = mongoose.model('Post', Post);
I expect the output to be...
[{"_id":"5d76a7e78b55cd3309b91ecf", "title": "blah", category: "blah", "content": "blah", "__v":0}]
But it is...
[{"_id":"5d76a7e78b55cd3309b91ecf","__v":0}]

Sorry figured it out myself. Form was outputting fields that weren't in the model. Changed form to...
<form id="add-form" method="POST" action="/makepost">
<label for="post_title">Title</label>
<input type="text" name="post_title">
<!-- <label for="post_category">Category</label>
<select name="post_category">
<option>Coding</option>
<option>Music</option>
<option>Books</option>
<option>Other Stuff</option>
</select> -->
<label for="post_date">Content</label>
<input type="date" name="post_date">
<label for="post_content">Content</label>
<input type="text" name="post_content">
<input type="submit">
</form>
Basically just changed the names of input fields to match the model.

Related

How do I fix this problem creating an Image object in MongoDB using ExpressJs, NodeJs, Handlebars, and Multer?

I am trying to build a website that allows a user to add a collectors item to the website. It has a form that requires certain fields to be filled out (I chose Funko Pop's). I have got everything working for the exception of having the image uploaded to the index.hbs page and into the MongoDB database.
Can anyone help? I think I am very close, but my terminal is throwing a Mongoose validator error (I'll show this at the end of the post)
The image seems to be sent to my "uploads" folder successfully, it just seems that there is some miscommunication happening with MongoDB because mongoose isn't happy.
Would anyone know what the issue is? And know how to fix it?
Thank you all for the help!
Here is my code:
Collection.js Controller/Route:
const express = require('express')
const router = express.Router()
const Collection = require('../models/collection')
const globalAuthFunction = require('./authenticationFunction')
const multer = require('multer')
// storage for multer
const storage = multer.diskStorage({
destination: function(err, file, callback){
callback(null, './public/uploads')
},
filename: function(req, file, callback){
callback(null, Date.now() + file.originalname)
}
})
const upload = multer({
storage: storage
})
router.get('/', (req, res) => {
Collection.find((err, collections) => {
if (err) {
console.log(err);
}
else {
res.render('collections/index', {
title: 'Collections',
collections: collections,
user: req.user
})
}
})
})
router.get('/create', globalAuthFunction.isAuthenticated, (req, res) => {
Collection.find((err, collections) => {
if(err){
console.log(err)
}
else{
res.render('collections/create', {
title: 'Add Employer',
collections: collections,
user: req.user,
})
}
})
})
router.post('/create', upload.single('image'), globalAuthFunction.isAuthenticated, (req, res) => {
Collection.create(req.body, (err, newCollection) => {
if (err) {
console.log(err)
}
else {
res.redirect('/collections')
}
})
})
router.get('/edit/:_id', globalAuthFunction.isAuthenticated, (req, res) => {
Collection.findById(req.params._id, (err, collection) => {
if(err){
console.log(err)
}
else{
res.render('collections/edit', {
title: 'Funko Pop Details',
collection: collection,
user: req.user,
image: req.file.filename
})
}
})
})
router.post('/edit/:_id', globalAuthFunction.isAuthenticated, (req, res) => {
Collection.findByIdAndUpdate({ _id: req.params._id}, req.body, null, (err, collection) =>{
if(err){
console.log(err)
}else{
res.redirect('/collections')
}
})
})
router.get('/delete/:_id', globalAuthFunction.isAuthenticated, (req, res) => {
Collection.deleteOne({ _id: req.params._id}, (err) => {
if(err){
console.log(err)
}
else{
res.redirect('/collections')
}
})
})
module.exports = router
My create.hbs:
<h1>Add a Funko Pop to Your Collection</h1>
<form method="post" enctype="multipart/form-data">
<fieldset>
<label for="character" class="col-2">Character: *</label>
<input name="character" id="character" required />
</fieldset>
<fieldset>
<label for="mediaTitle" class="col-2">Move or Television Name: *</label>
<input name="mediaTitle" id="mediaTitle" required />
</fieldset>
<fieldset>
<label for="category" class="col-2">Category: *</label>
<input name="category" id="category" required />
</fieldset>
<fieldset>
<label for="popNumber" class="col-2">Funko Pop Number: *</label>
<input name="popNumber" id="popNumber" required />
</fieldset>
<fieldset>
<label for="specialtySticker" class="col-2">Specialty Sticker: </label>
<input name="specialtySticker" id="specialtySticker" placeholder="N/A if there is no sticker"/>
</fieldset>
<fieldset>
<label for="price" class="col-2">Price: *</label>
<input name="price" id="price" required />
</fieldset>
<fieldset>
<label for="releaseYear" class="col-2">Funko Pop Release Year: *</label>
<input name="releaseYear" id="releaseYear" required />
</fieldset>
<fieldset>
<label for="image" class="col-2">Upload Image:</label>
<input type="file" name="image" id="image" value="image"/>
</fieldset>
<button class="btn btn-primary offset-2">Save</button>
</form>
My index.hbs:
<h1>Funko Pop Collection</h1>
{{#if user}}
<a class="btn btn-secondary" href="/collections/create">Add a Funko Pop</a>
{{/if}}
<section class="row">
{{#each collections}}
<div class="card col-2 m-2">
<div class="card-body text-center h-100">
<img src="{{this.image}}"/>
<h5 class="card-title">{{this.character}}</h5>
<p>Funko Pop Title: {{this.mediaTitle}}</p>
<p>Category: {{this.category}}</p>
<p>Pop Number: {{this.popNumber}}</p>
<p>Specialty Sticker: {{this.specialtySticker}}</p>
<p>Value: ${{this.price}}</p>
<p>Year:{{this.releaseYear}}</p>
{{#if ../user}}
<div>
Edit
Delete
</div>
{{/if}}
</div>
</div>
{{/each}}
</section>
My app.js:
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var indexRouter = require('./controllers/index');
var usersRouter = require('./controllers/users');
const collections = require('./controllers/collections')
const auth = require('./controllers/auth')
const passport = require('passport')
const session = require('express-session')
const multer = require('multer')
var app = express();
// database connection to MongoDB
if (process.env.NODE_ENV !== 'production'){
require('dotenv').config()
}
app.use(session ({
secret: process.env.PASSPORT_SECRET,
resave: true,
saveUninitialized: false
}))
app.use(passport.initialize())
app.use(passport.session())
const User = require('./models/user')
passport.use(User.createStrategy())
// let passport read/write user data to/from session vars
passport.serializeUser(User.serializeUser())
passport.deserializeUser(User.deserializeUser())
const google = require('passport-google-oauth20').Strategy
passport.use(new google({
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: process.env.GOOGLE_CALLBACK_URL
},
(accessToken, refreshToken, profile, done) => {
User.findOrCreate({ oauthId: profile.id}, {
username: profile.displayName,
oauthProvider: 'Google',
created: Date.now()
}, (err, user) => {
return done(err, user)
})
}
))
const mongoose = require('mongoose');
const { access } = require('fs');
mongoose.connect(process.env.DATABASE_URL)
.then(
(res) => {
console.log('Connected to MongoDB')
}
).catch(() => {
console.log('Cannot connect to MongoDB')
})
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hbs');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/collections', collections)
app.use('/auth', auth)
app.use('/', indexRouter);
app.use('/users', usersRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
This is what my terminal is showing when I try and create a new Funko Pop Object in MongoDB:
It is saying there is an incorrect path or something. The image is uploading correctly to my "uploads" folder, it just seems to be having an issue with the database connection.
I thought it may be that the image type in my model was wrong, so I switched it to "Buffer" instead of "String", but it still showed me the same exact error. I have watched several tutorials, but they have set it up completely different than mine.
They seem to be using a something like this in there "post" function in there controllers:
let connection = new Connection({
title: request.body.title,
img: request.file.filename
}
I do not know enough about handlebars, MongoDB or Multer to be able to diagnose the issues that is happening. Any help would be greatly appreciated.
Thank you!
since you are using multer, change it from request.file.filename to request.file.path

Node.js: Upload large file to MongoDB AND data from text inputs on the same page to different collections

Hello there and Happy New Year to all:)
In the .ejs file there are two forms: one to get text inputs, another for file upload:
<div class="sectionContainer">
<div class="tour-upload">
<form method="post" action="/office/new-tour">
<label for="tourHeading">Tour Heading <em>*</em></label
><input
id="tourHeading"
name="tourHeading"
required=""
type="text"
placeholder="eg May 31-June 11 (Riga, Amsterdam, Riga)"
/>
<label for="tourDescription"
>Tour Info <em>*</em></label
>
<textarea
id="tourDescription"
name="tourDescription"
required=""
placeholder="Add tour details"
rows="4"
></textarea>
<button id="add-tour">Add Tour</button>
</form>
<form action="office/add-score" method="POST" enctype="multipart/form-data">
<div class="custom-file mb-3">
<input type="file" name="file" id="file" class="custom-file-input">
<label for="file" class="custom-file-label">Choose File</label>
</div>
<input type="submit" value="Submit" class="btn btn-primary btn-block">
</form>
</div>
In order to get get the info from the form where action="/office/new-tour", I can use this code in app.js:
Setup:
const express = require("express");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const http = require("http");
const url = require("url");
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.set("view engine", "ejs");
And the actual code with logic:
app.get("/office", function (req, res) {
res.render("office");
});
//Mongo DB connection for form data saving
mongoose.connect("mongodb://localhost:27017/kbTourAppDB", {
useNewUrlParser: true,
useUnifiedTopology: true,
});
const ToursSchema = {
tour: { tourHeading: String, tourDescription: String },
program: { tourProgram: String, tourProgramDescription: String },
};
const Tour = mongoose.model("Tour", ToursSchema);
app.post("/office/new-tour", (req, res) => {
const addedTour = new Tour({
tour: {
tourHeading: req.body.tourHeading,
tourDescription: req.body.tourDescription,
},
program: {
tourProgram: req.body.tourProgram,
tourProgramDescription: req.body.tourProgramDescription,
},
//add author when the login page is ready
});
addedTour.save(function (err) {
if (err) {
console.log("err: ", err);
} else {
console.log("sucess added new Tour to db");
}
});
res.redirect("/office");
});
app.listen(3000, function () {
console.log("listening on port 3000");
});
The code above works successfully for getting those text inputs to database, however I can't use it to upload the files to the database (mostly jpeg and pdf). For that I found a solution with Multer and GridFS.
Set up:
const express = require("express");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const path = require("path");
const crypto = require("crypto");
const multer = require("multer");
const GridFsStorage = require("multer-gridfs-storage");
const Grid = require("gridfs-stream");
const methodOverride = require("method-override");
const http = require("http");
const url = require("url");
const app = express();
app.use(bodyParser.json());
app.use(methodOverride("_method"));
app.use(bodyParser.urlencoded({ extended: true }));
app.set("view engine", "ejs");
And code here:
app.get("/office", function (req, res) {
res.render("office");
});
const conn = mongoose.createConnection("mongodb://localhost:27017/kbTourAppDB");
let gfs;
conn.once("open", () => {
gfs = Grid(conn.db, mongoose.mongo);
gfs.collection("uploads");
});
//create storage object
const storage = new GridFsStorage({
url: "mongodb://localhost:27017/kbTourAppDB",
file: (req, file) => {
return new Promise((resolve, reject) => {
crypto.randomBytes(16, (err, buf) => {
if (err) {
return reject(err);
}
const filename = buf.toString("hex") + path.extname(file.originalname);
const originalFileName = file.originalname;
const fileInfo = {
filename: filename,
bucketName: "uploads",
};
resolve(fileInfo);
});
});
},
});
const upload = multer({ storage });
app.post("/office/add-score", upload.single("file"), (req, res) => {
res.redirect("/office");
});
app.listen(3000, function () {
console.log("listening on port 3000");
});
This code works for uploading files to database..
How can I write a code that will allow me to do both on the same page: upload the text input data to the MongoDB collection 'tour-data' for example, and the files from the other form to the collection 'uploads'..
Thank you very much for your help!
Actually when using multer, the text-fields from your form should still be populated under req.body.<field-name>, so you should be able to just use your initial code for inserting the tour-data:
app.post("/office/add-score", upload.single("file"), (req, res) => {
const addedTour = new Tour({
tour: {
tourHeading: req.body.tourHeading,
tourDescription: req.body.tourDescription,
},
program: {
tourProgram: req.body.tourProgram,
tourProgramDescription: req.body.tourProgramDescription,
}
});
addedTour.save(...)
});

TypeError Cannot set property 'firstName' of null

I know there are similar questions posted, but I haven't been able to find a solution for my problem.
I am trying to create a user profile page where the user can change their information through a form that uses a POST request. However, when the value is entered in the input field, it returns null. I don't have this problem when reading the input data for authenticating a user.
Also, the user is found but req.body returns an empty object.
Tools used:
Node.js v10.16.3
Express v4.17.1
ejs v2.7.1
Express session v1.16.2
Passport v^0.4.0
cookie-parser 1.4.4
body-parser v1.19.0
The user that is found:
{ _id: 5daf5ef80fb0d909e099d211,
username: 'assa',
email: 'easy#gmail.com',
password:
'$2b$05$A81bqD56TDmNoWhiHJVwR.2L7iqZBrRwYu1FEe/bp0TlkTMEUREvS',
firstName: 'test',
__v: 0 }
app.js:
let express = require("express"),
app = express(),
bodyParser = require("body-parser"),
cookieParser = require('cookie-parser'),
session = require("express-session"),
mongoose = require("mongoose"),
passport = require("passport"),
flash = require('connect-flash'),
validator = require('express-validator'),
LocalStrategy = require("passport-local"),
MongoStore = require('connect-mongo')(session);
let indexRoutes = require('./routes/index');
let userRoutes = require('./routes/user');
let User = require("./models/user");
// APP CONFIGURATION
mongoose.connect("mongodb://localhost:27017/test", { useNewUrlParser: true, useUnifiedTopology: true, }).then(() => {
console.log("Connected to MongoDB");
}).catch((error) => {
console.log("Something is wrong...");
});
require('./config/passport');
// View engine setup
app.set("view engine", "ejs");
app.use(express.static(__dirname + "/public"));
// Initial setup
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(validator());
// Session setup
app.use(cookieParser());
app.use(session({
secret: 'somesecretforbytox',
resave: false,
saveUninitialized: false
}));
app.use(flash());
// Initialize passport
app.use(passport.initialize());
app.use(passport.session());
app.use(function (req, res, next) {
res.locals.currentUser = req.user;
res.locals.session = req.session;
next();
});
// ======================
// Connect to route files
// ======================
app.use('/user', userRoutes);
app.use(indexRoutes);
app.listen(3033, function () {
console.log("Listening at port 3033...");
});
user.js
let express = require('express'),
router = express.Router(),
passport = require('passport');
let User = require("../models/user");
// user profile
router.get("/profile", isLoggedIn, function (req, res) {
res.render("user/profile", { currentUser: req.user });
});
router.post('/profile', (req, res) => {
updateRecord(req, res);
res.redirect('/user/profile');
});
function updateRecord(req, res) {
User.findOne({ 'id': req.user.id }, function (err, user) {
let firstName = req.body.firstName;
user.firstName = firstName;
user.save(function (err, doc) {
if (err) {
return done(err);
}
return done(null, doc);
});
});
}
router.get("/profile/edit", isLoggedIn, function (req, res) {
res.render("user/edit", { currentUser: req.user });
});
// ...sign in and signup routes
module.exports = router;
// middleware
function isLoggedIn(req, res, next) {
if (req.isAuthenticated()) {
return next();
}
res.redirect('/user/login');
}
profile.ejs:
<form action="/user/profile" method="POST" class="form-validate form-horizontal">
<fieldset>
<legend>Edit addresss</legend>
<!-- email -->
<div class="control-group">
<div class="control-label">
<label id="jform_email1-lbl" for="jform_email" class="hasPopover required" title="" data-content="Въведете имейл адрес." data-original-title="Email Address">
Email<span class="star"> *</span></label>
</div>
<div class="controls">
<input type="email" name="email" class="validate-email required" id="jform_email" value="<%= (typeof currentUser.email != 'undefined' ? currentUser.email : '') %>" size="30" autocomplete="email" required aria-required="true">
</div>
</div>
<!-- name -->
<div class="control-group">
<div class="control-label">
<label id="jform_fname-lbl" for="jform_fname" class="hasPopover required" title="" data-content="Въведете име." data-original-title="Name">
Name<span class="star"> *</span></label>
</div>
<div class="controls">
<input type="text" name="firstName" id="jform_fname" value="<%= (typeof currentUser.firstName != 'undefined' ? currentUser.firstName : '') %>" class="required" size="30" required aria-required="true">
</div>
</div>
</fieldset>
<div class="form-actions">
<!-- <input type="hidden" name="_csrf" value=" csrfToken "> -->
<button type="submit" class="btn btn-primary validate">
<span>Save</span>
</button>
<!-- <input type="hidden" name="_csrf" value=" csrfToken "> -->
<a class="btn" href="/" title="Cancel">Cancel</a>
</div>
</form>
user schema:
let mongoose = require('mongoose');
let Schema = mongoose.Schema;
let bcrypt = require('bcrypt');
let userSchema = new Schema({
username: { type: String, required: true },
email: { type: String, required: true },
password: { type: String, required: true },
firstName: { type: String },
lastName: { type: String },
address: { type: String },
zip: { type: String },
country: { type: String },
phone: { type: String }
});
userSchema.methods.encryptPassword = function (password) {
return bcrypt.hashSync(password, bcrypt.genSaltSync(5), null);
};
userSchema.methods.validPassword = function (password) {
return bcrypt.compareSync(password, this.password);
}
module.exports = mongoose.model('user', userSchema);
Changing the query to User.findOne({ '_id': req.user.id } as suggested by Subburaj and Matheus Hatje solved the issue.
Snapshot:
router.post('/profile', (req, res) => {
ModelName.create(req.body).then(result => {
if(result){
res.redirect('/user/profile');
}).catch(err){
res.send(err)
}
});
create function write separately, don't compare with update functions.

MERN Stack: POSTing data to database with Express/React

I'm new to the MERN stack and backend programming. I have a React form that I want to submit to an MLab database using Express. I am unable to successfully POST the form data to the database. I'm not sure if I'm taking the correct approach or not. My form is working and I am able to log the fields, I run into problems when trying to do a POST request to submit the form data.
Here is my form:
import React from 'react';
import { Button, Modal, ModalHeader, ModalBody, ModalFooter, Form, FormGroup, Label, Input } from 'reactstrap';
class AddBookModal extends React.Component {
constructor(props) {
super(props);
this.state = {
modal: false,
bookTitle: '',
author: '',
genre: ''
};
this.toggle = this.toggle.bind(this);
this.onSubmit = this.handleSubmit.bind(this);
}
toggle() {
this.setState(prevState => ({
modal: !prevState.modal
}));
}
handleSubmit = (event) => {
event.preventDefault();
const data = this.state;
//console.log("Data from form :" + data.bookTitle, data.author, data.genre);
}
handleInputChange = (event) => {
event.preventDefault();
this.setState({
[event.target.name]:
event.target.value
});
}
render() {
const {bookTitle} = this.state;
const {author} = this.state;
const {genre} = this.state;
return (
<div>
<Button id="add-book-button" onClick={this.toggle}>Add Book</Button>
<Modal isOpen={this.state.modal} toggle={this.toggle} className={this.props.className}>
<ModalHeader toggle={this.toggle}>Add Book</ModalHeader>
<ModalBody>
<Form method="POST" action="/profile" id="add-book-form" onSubmit={this.handleSubmit} >
<FormGroup>
<Label for="book-title-label">Book Title</Label>
<Input
value={bookTitle}
name="bookTitle"
onChange={this.handleInputChange}
placeholder="Enter name of book" />
</FormGroup>
<FormGroup>
<Label for="book-author-label">Author</Label>
<Input
value={author}
name="author"
onChange={this.handleInputChange}
placeholder="Enter author of book" />
</FormGroup>
<FormGroup>
<Label for="exampleSelect">Genre</Label>
<Input
onChange={this.handleInputChange}
value={genre}
type="select"
name="genre"
id="exampleSelect">
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</Input>
</FormGroup>
<ModalFooter>
<Button color="primary" type="submit" onClick={this.toggle}>Submit</Button>{' '}
<Button color="secondary" onClick={this.toggle}>Cancel</Button>
</ModalFooter>
</Form>
</ModalBody>
</Modal>
</div>
);
}
}
export default AddBookModal;
Here is my Express route:
const router = require('express').Router();
const bodyParser = require('body-parser');
var urlencodedParser = bodyParser.urlencoded({ extended: false });
// localhost:3000/profile
// User Model
const User = require('../../models/user-model');
const Book = require('../../models/book-model');
// Checks if user is not logged in
const authCheck = (req, res, next) => {
if(!req.user) {
// If user is not logged in, redirect them to login page
res.redirect('/auth/login');
}
else {
// If user is logged in call next in router.get
next();
}
};
router.get('/', authCheck, (req, res) => {
res.send('you are logged in, this is your profile : ' + req.user);
});
router.post('/', urlencodedParser, (req, res) => {
console.log(req.body);
const newUser = new User({
name: req.body.name,
username: req.body.username,
githubID: req.body.githubID,
profileUrl: req.body.profileUrl,
avatar: req.body.avatar,
books: {
bookTitle: req.body.bookTitle,
author: req.body.author,
genre: req.body.genre
}
});
newUser.save()
.then(data => {
res.json(data)
})
.catch(err => {
res.send("Error posting to DB")
});
});
module.exports = router;
Here is my Express server:
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const authRoutes = require('./routes/api/auth');
const passportSetup = require('./config/passport-setup');
const cookieSession = require('cookie-session');
const keys = require('./config/keys');
const passport = require('passport');
const profileRoutes = require('./routes/api/profile-routes');
const bookRoutes = require('./routes/api/book-routes');
// Hooks up routes/api/items file
const items = require('./routes/api/items');
const app = express();
// Boderparser Middleware
app.use(bodyParser.json());
// sets up session cookies
app.use(cookieSession({
// Max age set to 1 day
maxAge: 24 * 60 * 60 * 1000,
// Uses cookieKey from keys file to encrypt
keys: [keys.session.cookieKey]
}));
// initialize passport
app.use(passport.initialize());
app.use(passport.session());
// DB Config
const db = require('./config/keys').mongoURI;
// Connect to mongodb
mongoose
.connect(db, { useNewUrlParser: true })
.then(() => console.log('MongoDB Connected'))
.catch(err => console.log(err));
// Use Routes, sets up routes/api/items to be used
app.use('/api/items', items);
app.use('/book', bookRoutes);
// Use auth.js's routes
app.use('/auth', authRoutes);
// Use profile-routes routes for profile page
app.use('/profile', profileRoutes);
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`Server started on port ${port}`))
I'm unable to make a POST request and not sure why. The Express route handles some OAuth stuff and displays the logged in user's profile. On that same page I have the form which allows the user to add data and submit it. Is the logic from authCheck interfering with POSTing the form data? The router.post in my Express route does not successfully console.log anything.
I've seen people use Axios in the React form component itself to do a POST request. Is it better to do form POST requests with Axios or should I be handling it in the Express route?
You should use the axios for making the api call.
In your handleSubmit function you are using "event.preventDefault()" which will prevent the default behavior of the form.

How do I add a record into MongoDb using Apache Kafka in NodeJS?

I am experimenting with Apache Kafka, NodeJS and MongoDB. I have a simple program below that simply adds my name to a mongodb to practice. I am trying to fuse it with Kafka and it is not working the way I would like it too. See code below.
index.html
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<form method="post" action="/addname">
<label>Enter Your Name</label><br>
<input type="text" name="firstName" placeholder="Enter first name..."
required>
<input type="text" name="lastName" placeholder="Enter last name..."
required>
<input type="submit" value="Add Name">
</form>
</body>
</html>
index.js
const express = require("express");
const mongoose = require("mongoose");
const bodyParser = require('body-parser');
const kafkaSend = require('./kafka/kafkaScripts/producer.js');
const kafkaRead = require('./kafka/kafkaScripts/consumer.js');
const app = express();
const port = 3000;
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
mongoose.Promise =
global.Promise;mongoose.connect("mongodb://localhost:27017/q-research");
var nameSchema = new mongoose.Schema({
firstName: String,
lastName: String
});
var User = mongoose.model("User", nameSchema);
app.post("/addname", (req, res) => {
var myData = new User(req.body);
myData.save()
.then(item => {
let testObj ={
type: item,
userId:'userID',
sessionId: 'whateverSessionId',
data: item
};
kafkaSend.sendRecord(testObj,function(err,data){
if(err){
console.log('error: ', err);
}
else{
res.send("item saved to database");
}
});
})
.catch(err => {
console.log('err: ', err);
res.status(400).send("unable to save to database");
});
});
/* app start info */
app.use("/", (req, res) => {
res.sendFile(__dirname + "/index.html");
});
app.get("/", (req, res) => {
res.send("Hello World");
});
app.listen(port, () => {
console.log("Server listening on port " + port);
});
producer.js
const kafka = require('kafka-node'),
uuid = require('uuid');
const client = new kafka.Client("localhost:2181", 8, {
sessionTimeout: 300,
spinDelay: 100,
retries: 2
});
const producer = new kafka.HighLevelProducer(client);
producer.on("ready", function() {
console.log("Kafka Producer is connected and ready.");
});
// For this demo we just log producer errors to the console.
producer.on("error", function(error) {
console.error(error);
});
const KafkaService = {
sendRecord: ({ type, userId, sessionId, data }, callback = () => {}) => {
if (!userId) {
return callback(new Error(`A userId must be provided.`));
}
const event = {
id: uuid.v4(),
timestamp: Date.now(),
userId: userId,
sessionId: sessionId,
type: type,
data: data
};
const buffer = new Buffer.from(JSON.stringify(event));
// Create a new payload
const record = [
{
topic: "webevents.dev",
messages: buffer,
attributes: 1 /* Use GZip compression for the payload */
}
];
//Send record to Kafka and log result/error
producer.send(record, callback);
}
};
module.exports = KafkaService;
I am getting the below error. So here is where my question comes in. I believe I need to change my type in my test object then it might work. I'm not sure it. It could could additional things too.
All I had to do was point to my virtual box instead of my localhost since my kafka is in a Ubuntu box.
const client = new kafka.Client("10.10.205.17:2181, 8, {
sessionTimeout: 300,
spinDelay: 100,
retries: 2
});

Resources