NodeJS trouble sending messages to client - node.js

I am trying to learn Node.JS, but making a REST API using this tutorial:
https://medium.freecodecamp.org/building-a-simple-node-js-api-in-under-30-minutes-a07ea9e390d2
I am having a very stupid little issue I can't seem to fix. In my user_routes.js file, I am trying to write several messages to the express() app, however it never works after the first res.send() call. Why is this? I can't find anywhere in my code where I am closing the connection or whatever, so why can't I write more than once to the request?
My user_routes.js
module.exports = function(app, db) {
app.post('/user', function (req,res) {
res.send("User Request Recieved via POST");
// Add the user to the database, if they don't already exist
const firstName = req.body.firstName;
const lastName = req.body.lastName;
const email = req.body.email;
const password = req.body.password;
const user = {
firstName: firstName,
lastName : lastName,
email : email,
password : password
};
if (db.collection('users').find({'email':email}).count() == 0) {
res.send('Unique Email');
db.collection('users').insert(user, (err, result) => {
if (err) {
console.log("error");
} else {
console.log(result.ops[0])
}
});
} else {
res.send("Email already in use")
}
})
};
Any my server.js:
const express = require('express');
const MongoClient = require('mongodb').MongoClient;
const bodyParser = require('body-parser');
const app = express();
const port = 6969;
const db = require('./config/db')
// We need to decode data from the url using the body-parser lib
app.use(bodyParser.urlencoded({ extended: true }));
MongoClient.connect(db.url).then( function(db) {
require('./app/routes')(app, db);
app.listen(port, () => {
console.log('We are live on ' + port);
});
}).catch (function (err) {
console.log(err);
});
module.exports = app;
I don't seem to close the connection anywhere, so why is it I am only able to write one message to the client?

res.send() is the last thing your function should be doing. Think of it like a return for your function, you can't return multiple times.

res.send() == return()
res.send() is equivalent to "return" for your post -- you can only do it once per call.
Multiple Messages per res.send()
If you want to send multiple messages through one call, you need to compile an object/array of messages you want to send and send that object/array through your res.send(). Example:
ret_msg = [];
ret_msg.push("Here's your first message.");
ret_msg.push("Here's your second message.");
ret_msg.push("Here's your third message.");
res.send(ret_msg);

Related

Lose access to part of my database when I switch to a different server location

Context: I am using mongoDB to store my data on my first API, it's made in node.js. I'm currently working on creating a login system. When I post the account to my API I set the _id value to the email address so to access it I can just do api.com/logins/email. Whenever I do that I get this in return
{"_id":"email","password":"password","__v":0}
However when I switch the server location (from my server to my laptop for dev testing) I can no longer access the logins by _id. I can still access the entire collection, but when I attempt to call specifically by the _id I get Cannot GET /logins/email This also happens if after the fact I reopen the API server on my personal server
In order to fix this I have to delete all the collections in that area and re add one from the app. Once I do this everything works again however when my app goes live I would want to have this fixed because otherwise everyone would need to remake their accounts when I do work on the API
With this being my first API I'm kind of at a loss for what's happening and why it is, any help would be appreciated
Relevant code from sign in page (yes I am aware that base64 isn't encrypting I just haven't change it yet)
const login = async () =>{
encrypted = (await encrypt())
console.log(email.toUpperCase())
var mail = email.toUpperCase()
var test = await fetchSingleData(url,mail)
console.log(test)
if (test==null){
console.log("Invalid email")
return
}
console.log(test.password == encrypted)
if (encrypted == test.password){
console.log("I'm in")
setEmail("")
setPassword("")
navigation.navigate("Sheet")
}
else console.log("Invalid Password")
}
const encrypt = async () =>{
var enc = Base64.encode(password)
console.log(enc)
return enc
}
Mongoose connection code
const express = require('express')
const app = express()
const mongoose = require('mongoose')
require('dotenv/config')
const bodyParser = require('body-parser')
const MONGOBD_URL = process.env.DB_CONNECTION
var https = require("https")
var fs = require("fs");
var path = require("path")
app.use(bodyParser.json())
//Import routes
const postsRoute = require('./routes/posts')
const loginRoute = require("./routes/logins")
app.use('/posts', postsRoute)
app.use('/logins', loginRoute)
//ROUTES
app.get('/',(req,res)=>{
res.send("We are on home")
})
//LISTENER
app.listen(19010)
//Connect to DB
mongoose.connect(MONGOBD_URL,{useNewUrlParser:
true},()=>{console.log("connected to DB")})
module.exports = app;```
Routing
const express = require('express')
const router = express.Router();
const Login = require("../Models/Login")
//GET ALL ACCOUNTS
router.get('/',async (req,res)=>{
console.log("req")
try{
const logins = await Login.find()
res.json(logins)
}catch(err)
{
res.json({message: err})
}
})
// CREATES ACCOUNT
router.post('/', async (req,res) => {
const login = new Login({
_id: req.body._id,
password: req.body.password
})
//SPECIFIC ACCOUNT
router.get('/:postID', async (req,res) =>{
try{
const login = await Login.findById(req.params.postID)
res.json(login)
}
catch(err){res.json({message:err})}
})
const savedLogin = await login.save()
try{
res.json(savedLogin)
}catch(err){
res.json({message: err})
}
})
//DELETE ACCOUNT
router.delete('/:postID', async (req,res) => {
try{
const remove = await Post.remove({_id:req.params.postID})
res.json(remove)
}
catch(err){res.json({message:err})}
})
module.exports = router
Data example in database
okay so let us get to this...I'm not too sure what the cause of this issue is, but let us go through your code and try to isolate it. So we will begin by neatening things up a little.
starting with your login code:
const login = async () => {
encrypted = (await encrypt())
var mail = email.toUpperCase()
var test = await fetchSingleData(URL, mail)
// [TIP]: this is sufficient to achieve the same logic.
if (!test) {
return
}
if (encrypted == test.password) {
setEmail("")
setPassword("")
navigation.navigate("Sheet")
}
else
console.log("Invalid Password")
}
//...
const encrypt = async () => {
return Base64.encode(password)
}
Okay let check out your route configuration.
// [TIP]: import everything first
const express = require('express')
const mongoose = require('mongoose')
const bodyParser = require('body-parser')
// [TIP]: const on everything that wont change
const https = require("https")
const fs = require("fs");
const path = require("path")
require('dotenv/config')
const MONGOBD_URL = process.env.DB_CONNECTION
const app = express()
app.use(bodyParser.json())
//Connect to DB
// [FIX]: Connect to the database first before referencing it in your routes
// [NOTE]: Express is a static server and cannot change after configuring
// the routes that you have.
mongoose.connect(MONGOBD_URL,
{ useNewUrlParser: true },
() => console.log("connected to DB"))
//Import routes
const postsRoute = require('./routes/posts')
const loginRoute = require("./routes/logins")
// I do not know what goes on here
app.use('/posts', postsRoute)
// or here, but suspect your issue lies here.
app.use('/logins', loginRoute)
//ROUTES
app.get('/', (req, res)=>{
res.send("We are on home")
});
//LISTENER
app.listen(19010, () => console.log('server listening on port 19010'));
module.exports = app;
Im still not sure what the problem could be with this code, my suspicion is still with your database connection.
So in the end the issue was my brackets. They were set up in a way that so that the singular get was only created when I did a POST

socket.io connects with same socket id

my socket creates problem when frontend loads before the server,
My problems are
1.I get same the socketid from the cookies of multiple clients
2.I get only one client who is connected with multiple socketids from the server
3.When I get this problem, my API calls will not work and I won't get any data from my database
I also get this problem when I restart the server, and when I refresh the frontend multiple times with different clients
my server side code
const mongoose = require("mongoose");
express = require("express");
app = express();
bodyParser = require("body-parser");
cookieParser = require("cookie-parser");
cors = require("cors");
user = require("./routes/user");
message = require("./routes/message");
http = require("http");
server = http.createServer(app);
io = require("socket.io")(server);
var userdata = require("./controllers/user");
mongoose
.connect(process.env.DATABASE, {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
})
.then(() => {
console.log("DB CONNECTED");
})
.catch((err) => console.log(err));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser());
app.use(cors());
app.use(express.json());
app.use("/use", user);
app.use("/use", message);
let users = [];
io.on("connection", (socket) => {
socket.on("done", () => {
let userdata = require("./controllers/user");
console.log("connected");
userdata.userdata &&
users.push({ userid: userdata.userdata._id, socketid: socket.id });
console.log(users);
});
socket.broadcast.emit("message");
socket.on("more", function (c) {
console.log(c.a, c.b);
let d = users.find((s) => s.userid === c.b);
if (d) {
return io.to(d.socketid).emit("message", c);
}
});
socket.on("disconnect", () => {
console.log(socket.id);
if (users) {
for (let e = 0; users.length; e++) {
if (users[e] && users[e].socketid === socket.id) {
return users.splice(e, 1);
}
}
}
console.log(users);
return console.log("disconnected");
});
});
// app.use();
const port = process.env.PORT || 8000;
server.listen(port, () => {
console.log(`app is running at ${port}`);
});
I found that my problem is caused by userdata, when I had deleted everything related to userdata, I didn't get any problem even when the server is reloaded.
Here userdata comes from a middileware called isSignedIn,this middleware is called before every API call from this webpage, so userdata gets updated frequently by the frontend code.This is my isSignedIn function
exports.isSignedIn = async (req, res, next) => {
const header = req.headers["authorization"];
const token = header && header.split(" ")[1];
if (!token) return res.json("no token");
jwt.verify(token, "jsdhbcjsd", (err, User) => {
if (err) return res.json(`${err} not signedin`);
req.User = User;
exports.userdata = User;
next();
});
};
I tried to call isSignedIn() instead of importing userdata, which would be lot better, but I was getting an error from the headers, so I couldn't call this function.
error I get when I call this function isSignedIn()
Promise {
<rejected> TypeError: Cannot read property 'headers' of undefined
at exports.isSignedIn (D:\message\backend\controllers\user.js:86:22)
it tells about this line
const header = req.headers["authorization"];
I made sure that the socket gets connected in the frontend only after calling the APIs using await,so that the userdata gets updated before connecting to the socket.I had tested it in the console,socket gets connected only after calling APIs
async componentDidMount() {
//my API calls
await this.friends(token);
await this.findfriends(token);
//connect the socket
this.start();
this.recieve();
}}
My frontend code
const client = require("socket.io-client");
var socket
export default class Home extends Component {
constructor(props) {
super(props);
this.start = this.start.bind(this);
this.send = this.send.bind(this);
this.recieve = this.recieve.bind(this);
this.friends= this.friends.bind(this);
this.findfriends= this.findfriends.bind(this);
}
start(){
socket=client("http://localhost:8000");
}
send(){
socket.emit("more", c)
}
recieve(){
socket.on("message", c)
}
async componentDidMount() {
//my API calls
await this.friends(token);
await this.findfriends(token);
//connect the socket
this.start();
this.recieve();
}}
render(){
return(my data)
}
}
After thinking for a while about requesting headers,which isn't possible, I thought, why couldn't I get userid from the socket when just it gets connected, then I tried this code, it worked perfectly fine
client side
start = () => {
socket = client("http://localhost:8000");
socket.on("connect", () => {
return socket.emit("userinfo", this.state.User._id);
});
};
server side
socket.on("userinfo", function (user) {
users.push({ userid: user, socketid: socket.id });
console.log("C O N N E C T E D");
});
You can't reassign exports.userdata = User; in middleware. That will affect every single request that uses those exports so they will all end up looking at the same userdata, no matter which user they are. That's the source of your confusion. There's only one exports object for each module and everyone who uses that module sees the same exports object. So, you can't use exports for request-specific data.
I see you are already assigning req.User = User. That is an appropriate place to put request-specific data and other users of that data in the processing of the request should get the data from req.User, not from the exported object. That will keep the data separate for each request and each user.

Router.express() -> What is the proper way for expressing router.use?

For router.use, it does not work like this anymore:
router.use("/api", apiRoutes);
Instead an error is thrown:
throw new typeerror('router.use() requires a middleware function but got a ' + gettype(fn))
How do I re-purpose that expression so that it works? I have not found any examples that were useful so far. Here is some of my sample code:
routes/index.js (this does not work)
const path = require("path");
const router = require("express").Router();
const apiRoutes = require("./api");
// API Routes
router.use("/api", apiRoutes);**// this throws an error**
router.use(function(req, res) {
res.sendFile(path.join(__dirname, "../client/build/index.html"));
});
module.exports = router;
Here is an example of my attempt to re-purpose but I do not think it's correct:
var path = require("path");
var router = require("express").Router();
var apiRoutes = require("./api");
//API Routes
//authRouter.use(require('./authenticate').basic(usersdb))
//router.use("./api", apiRoutes);
console.log("Hitting API routes...")
router.use("./api", function(req, res, next) { **//re-purpsose attempt here**
res.send(apiRoutes)
console.log("API Routes:", apiRoutes)
next()
});
console.log("API Routes hit")
// //If no API routes are hit, send the React app
// router.use(function(req, res) {
// res.sendFile(path.join(__dirname, "../client/public/index.html"));
// });
module.exports = router
This is the overall error I'm getting (404 returned):
GET /api/website_1_function_call/scrape 404 4.004 ms - 173
I know that this may be due to something else indirectly but I really am not sure about the router.use part.
I know for sure that the routes are not being hit properly and would like to fix.
Any advice would be appreciated. Thank you in advance.
Here is more code:
server.js
require("dotenv").config();
var express = require("express");
var cors = require('cors');
var bodyParser = require('body-parser');
var logger = require("morgan");
//const mongoose = require("mongoose");
var db = require("./models")
var routes = require("./routes");
var app = express();
var PORT = process.env.PORT || 3001;
var path = require('path');
//Define middleware here
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(bodyParser.json());
//Serve up static assets (usually on heroku)
if (process.env.NODE_ENV === 'production') {
app.use(express.static("client/build"));
}
app.use(cors());
app.use(logger("dev"));
//Add routes, both API and view
app.use(routes);
//replaced with below:
//app.use(app.router);
//routes.initialize(app);
// //Connect to the Mongo DB
// mongoose.connect(process.env.MONGODB_URI || "mongodb://localhost/kaibru");
var syncOptions = { force: false };
// If running a test, set syncOptions.force to true
// clearing the `testdb`
if (process.env.NODE_ENV === "test") {
syncOptions.force = true;
};
// Starting the server, syncing our models ------------------------------------/
db.sequelize.sync(syncOptions).then(function() {
app.listen(PORT, function() {
console.log(
"==> 🌎 Listening on port %s. Visit http://localhost:%s/ in your browser.",
PORT,
PORT
);
});
});
// //Start the API server
// app.listen(PORT, function() {
// console.log(`🌎 ==> API Server now listening on PORT ${PORT}!`);
// });
routes/index.js
var path = require("path");
var router = require("express").Router();
var apiRoutes = require("./api");
//API Routes
//authRouter.use(require('./authenticate').basic(usersdb))
//router.use("/api", apiRoutes);
console.log("Hitting API routes...")
router.use("/api", function(req, res, next) { // this is my re-purpose
attempt
apiRoutes
console.log("API Routes:", apiRoutes)
// next()
}); // this is my r-purpose attempt
console.log("API Routes hit")
// //If no API routes are hit, send the React app
// router.use(function(req, res) {
// res.sendFile(path.join(__dirname, "../client/public/index.html"));
// });
module.exports = router
routes/api/index.js
var router = require("express").Router();
require("./website_1");
var website_1Routes = require("./website_1_function_call");
//const userRoutes = require("./user");
//Website_1 routes
//http://localhost:3000/api/website_1_function_call/scrape
//authRouter.use(require('./authenticate').basic(usersdb))
//router.use("/website_1_function_call", website_1Routes);
//experimental use
router.use("/website_1_function_call", function(req, res, next) { // this is my re-purpose attempt
website_1Routes
console.log("website_1Routes:", website_1Routes)
// next()
}); //this is my re-purpose attempt
//router.use("/user", userRoutes);
module.exports = router
routes/api/website_1_function_call.js
require("./website_1");
require("./website_1_db");
require("./website_1_router");
//Call scrape functions from website_1 file
mainscrape();
//specificScrape() //let's leave this one dormant for now
//Now for saving to database
saveToDatabase();
//Now for the routes
routing();
I think my re-purpose attempt worked ( I removed next() since there are no defined routes right after). It seems to be processing. However, now my response hangs and this happens:
GET /api/website_1_function_call/scrape - - ms - -
This prints in the browser console:
GET http://localhost:3000/api/website_1_function_call/scrape
net::ERR_EMPTY_RESPONSE
0.chunk.js:871 Uncaught (in promise) Error: Network Error
at createError (0.chunk.js:871)
at XMLHttpRequest.handleError (0.chunk.js:366)
So now I think my scraper code and my code to update the database does not work.
Scrape function code:
//var express = require("express");
var router = require("express").Router();
require("../../controllers/website_1controller");
//requiring this website's models
var Items_1 = require("../../models/website_1");
//require("./website_1_db");
//require("./website_1_router");
// Our scraping tools
// Axios is a promised-based http library, similar to jQuery's Ajax method
// It works on the client and on the server
var axios = require("axios");
var cheerio = require("cheerio");
mainscrape = function() {
//Now to configure the routes
router.get("/scrape", function(req, res) {
//instead of simple res.render, user router.get
console.log("scraping started...");
//Grab the html body with axios
axios.get("url placeholder").then(function(response) {
//Load to cheerio and save to $ selector
console.log("Scraping all greenheartshop mainpage...");
var $ = cheerio.load(response.data);
var output = [];
var promises = [];
//Now we need to grab the title reference for each article
$("article").each(function(i, element) {
//save empty result object
var result = {};
//thumbnail
result.thumbnail = $(this)
//.children("article.product-grid-item.product-block").html()
.children("figure.product-item-thumbnail")
.children("a")
.attr("href")
//console.log("result thumbnail")
//console.log(result)
console.log(result.thumbnail)
var result = {}
//details
result.detail= $(this)
//.children("product-item-mask").html()
.children("div.product-item-details")
// .children("div.product-item-brand")
// .children("h5.product-item-title")
// .children("a")
// .children("div.product-item-price")
//.children("product-price-line")
//.children("price-value")
.text()
//result.detail = result.detail.trim();
//console.log("result detail")
//console.log(result)
console.log(result.detail)
//Capture the scraped data and save to database
console.log("Capturing Scrape")
if(result.detail !== '') {
var promise = Items_1
.saveToDatabase(result, result, {upsert:true, new:true})
console.log("saveToDatabase");
promises.push(promise);
}
Promise.all(promises).then((data) => {
res.json(data);
});
//saveToDatabase();
// if (result.thumbnail !== {} && result.detail !== "") {
// var promise = Items_1
// // .items_1_create({
// // resultThumbnail: result.thumbnail,
// // resultDetails: result.detail
// // })
// promises.push(promise)
// // .then(dbModel => output.push(dbModel));
// Promise.all(promises).then((data) => {
// res.json(data)
// })
// }
});
});
//Now to CREATE the results using controller file
// console.log("creating items in the database now...")
// router.post('/scrape', website_1Controller.items_1_create);
//Now to display the results
// console.log("Items now being displayed...")
// router.get('/scrape/display', website_1Controller.items_1_list)
});
}
module.exports = router;
module.exports = mainscrape;
module.exports = specificScrape;
Code to update the database:
require("../../controllers/website_1controller");
require("./website_1");
var Items_1 = require( "../../models");
//After scraping the main page, the following function is to save to the
database
saveToDatabase = function() {
//prepare the data
var result = {}
var dataToStore = Items_1.items_1_create
console.log(dataToStore)
//console.log(items_1_create)
//insert data to the database
// dataToStore.save().// We will not sue this part for now
// then(() => {
// console.log("Data successfully saved");
// }).catch(err => {
// console.log("Error: ", err);
// });
}
module.exports = saveToDatabase;
Code for final routing (after scrape is complete)
var website_1Controller = require("../../controllers/website_1controller");
var router = require("express").Router();
routing = function() {
//Now to CREATE the results using controller file
console.log("creating items in the database now...")
//router.route("/browse")
router.post('/browse', website_1Controller.items_1_create);
router.get('/browse', website_1Controller.items_1_list);
//Now to display the results
console.log("Items now being displayed...")
//router.route("/browse:search")
router.get('/:search', website_1Controller.items_1_specific);
};
require("./website_1");
module.exports = routing;
module.exports = router;
models
'use strict';
// Dependencies
// =============================================================
// Sequelize (capital) references the standard library
//var Sequelize = require("sequelize");
// sequelize (lowercase) references our connection to the DB.
//var sequelize = require("../config/connection.js");
// Creates a "Items_1" model that matches up with DB
module.exports = function(sequelize, DataTypes) {
var Items_1 = sequelize.define("Items_1", {
// the routeName gets saved as a string
detail: DataTypes.STRING,
// the name of the character (a string)
thumbnail: DataTypes.BLOB,
// the character's role (a string)
//role: Sequelize.STRING,
// the character's age (a string)
//age: Sequelize.INTEGER,
// and the character's force points (an int)
//forcePoints: Sequelize.INTEGER
}, {
// disable the modification of tablenames; By default, sequelize will
automatically
// transform all passed model names (first parameter of define) into
plural.
// if you don't want that, set the following
freezeTableName: true
});
return Items_1;
//Syncs with DB
//Items_1.sync();
// Makes the Items_1 Model available for other files (will also create a table)
};
controller
// *********************************************************************************
// website_1controllers.js - this file offers a set of routes for displaying and saving data to the db
// *********************************************************************************
// Dependencies
// =============================================================
var db = require("../models");
//display results for mainpage scrape
exports.items_1_create = function(req, res) {
db.Items_1.findOneAndUpdate(req.body, req.body, {upsert: true, new:
true})
.then(dbModel => res.json(dbModel))
.catch(err => res.status(422).json(err))
console.log("findOneAndUpdate complete")
},
exports.items_1_list = function(req,res) {
db.Items_1.findAll({})
},
exports.items_1_specific = function(req,res) {
db.Items_1.findById(req.params.search)
},
function(err, results) {
if (err) { return next(err); } //Error in API usage.
if (results.result.thumbnail==={} && results.result.detail==="") {//No
Results.
var err = new Error('Results not found');
err.status = 404;
return next(err)
}
//Successful, so render
res.render("click_results", { title: 'Click Results', resultThumbnail:
result.thumbnail, resultDetails: result.detail });
}
So the new issue is that the response hangs. I think it's because the code to update the database does not work (using sequelize). Let me know if anything else is needed and thank you in advance.
Thanks for all of the input everyone. After reviewing I found out that the function itself does not have to be re-purposed as I initially thought... I didn't know that if, for example, you are using "router.use("/directoy", directory) and you are using it in succession to point to different directories, the final directory hit must have a defined route like router.get(). I modularized my code to the point where the final directory was just a list of functions (one of these functions had the router.get method). This did not work. When I point the file directly to the code containing the router.get method, my scraped data returns to the terminal. Just thought I'd share my findings at least because I didn't know this at all . Many thanks to #mehta-rohan and #Anand Undavia for the insights. I'm still trying to get the data to render to the page but that's a different problem altogether.

post request not taking in data - express js and mongo

I am using this code:
app.post("/users", function(req, res) {
db.collection(USERS_COLLECTION).insertOne(req.body , function(err, doc) {
if (err) {
handleError(res, err.message, "Failed to create new user.");
} else {
res.status(201).json(req.body);
}
});
});
and I am trying putting in this request: localhost:8080/users?firstName=foo&lastName=bar
but when I try the post request in postman it returns just an id and doesn't insert the params in the database.
{
"_id": "584f04eb141faa7df7fc4059"
}
how do I fix this so that it returns the data or do I need to create a schema first and check against it? If I could be pointed in the right direction that would be great
You're correct in that you need a schema!
If there were no schema in a database, you essentially would have a bucket full of (potentially) mismatched JSON objects. Thus, it would be tedious to ensure that your keys match up to their expected values.
If you're new to Mongo, I'd recommend checking out Mongoose ODM. It helps when trying to understand the structure and quirks of a NoSQL DB.
ok.. So I created a Schema
var mongoose = require('mongoose');
// user schema
var usersSchema = mongoose.Schema({
firstName: String,
lastName : String,
email : String
});
mongoose.model('users', usersSchema);
and the post request code looks like this:
var express = require("express");
var path = require("path");
var bodyParser = require("body-parser");
var mongodb = require("mongodb");
var ObjectID = mongodb.ObjectID;
var USERS_COLLECTION = "users";
var mongoURL = "the url is here";
var user = require("./Models/User");
var mongoose = require('mongoose');
var app = express();
app.use(express.static(__dirname + "/public"));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
mongoose.connect(mongoURL);
// USERS API ROUTES BELOW
// Generic error handler used by all endpoints.
function handleError(res, reason, message, code) {
console.log("ERROR: " + reason);
res.status(code || 500).json({"error": message});
}
/* "/USERS"
* POST: creates a new user
*/
app.post("/users", function(req, res) {
var firstName = req.params.firstName;
var lastName = req.params.lastName;
var email = req.params.email;
//call the create function for our database
mongoose.model('users').create({
firstName : firstName,
lastName : lastName,
email : email
}, function (err, user) {
if (err) {
res.send("There was a problem adding the information to the database.");
} else {
//User has been created
console.log('POST creating new users: ' + user + firstName);
res.format({
//JSON response will show the newly created user
json: function(){
res.json(user);
}
});
}
})
});
though the issue is that when I send a http post request :
localhost:8080/users?firstName=foo&lastName=bar&email=foobar#gmail.com
req.body.firstName = undefined and req.params.firstName = undefined how do I get it to properly read in the values? When I put static strings in the place of req.body... it works perfect.
this is what returns in json currently:
{
"__v": 0,
"_id": "5851567048018fa141543f53"
}
21 things matter the most on this problem
you do not implement a body-parser
here you can install it by: npm I body-parser
app.use(express.json());
app.use(bodyParser.urlencoded({extended:true}));
app.use(bodyParser.json());
add content type in postman if you use postman to send API
Content-Type: application/JSON

Saving data to PostgreSQL when typing a slash command in Slack

I'm trying to build a bot for Slack that has some slashes commands. I'm totally new to Node.js and Slack, and I'm having huge problems to make it work, starting with the fact I cannot even know the reasons it fails.
I'm storing my bot in Heroku and I have a status table in there as well. I want to, when typing /here, to store the user's username and add a status 'here' to the database for further selection. My code's like this:
app.post('/here', function(req, res, next) {
var username = req.body.user_name;
pg.connect(process.env.DATABASE_URL, function(err, client, done) {
client.query('INSERT INTO status(username, status) VALUES($1, $2)', [username, 'here']);
var botPayload = {
text: 'Your status is now set to HERE'
};
return username !== 'slackbot' && !err
? res.status(200).json(botPayload)
: res.status(200).end();
});
});
This piece of code is based on a tutorial I found summed with other tutorials of how to connect and insert data into PostgreSQL, but when typing it in Slack channel, I receive the HTML of the Appliation Error page.
This is my full code. Only one file so far.
'use strict';
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
var port = process.env.PORT || 3000;
var pg = require('pg');
pg.defaults.ssl = true;
app.use(bodyParser.urlencoded({extended: true}));
app.get('/', function(req, res) {
res.status(200);
res.send('Hello World');
});
app.post('/hello', function(req, res, next) {
var username = req.body.user_name;
var channel = req.body.channel_name;
var botPayload = {
text: 'Hello ' + username + ', welcome to channel ' + channel + ' :-)'
};
return username !== 'slackbot'
? res.status(200).json(botPayload)
: res.status(200).end();
});
app.post('/here', function(req, res, next) {
var username = req.body.user_name;
pg.connect(process.env.DATABASE_URL, function(err, client, done) {
client.query('INSERT INTO status(username, status) VALUES($1, $2)', [username, 'here']);
var botPayload = {
text: 'Your status is now set to HERE'
};
return username !== 'slackbot' && !err
? res.status(200).json(botPayload)
: res.status(200).end();
});
});
app.listen(port, function() {
console.log('Server is running on port', port);
});
This piece of code is based on a tutorial I found summed with other tutorials of how to connect and insert data into PostgreSQL
It does not seem that way, as you made too many errors in your database code:
You are not checking for err after the connection, so if your connection fails, the rest will fail as well
You are not providing any callback on event handlers to get the result of the query you are executing
You are not releasing the connection back to the pool by calling done()
All of the above is necessary, and would be included in any manual that's out there, starting from the pg driver itself: Client Pooling.

Resources