I have a React app running Express querying a remote Postgres instance. I've set up some API routes to return data. When running locally, the data is returned as application/json, however when deployed to EC2 the same queries are returned as text/html so I cannot access it.
Here's some of the server code
require("dotenv").config();
const express = require("express");
const cors = require("cors");
const axios = require("axios");
const config = require("./config");
const path = require("path");
const db = require("./db");
const PORT = process.env.PORT || 8080;
const bodyParser = require("body-parser");
const app = express();
const pdf = require('html-pdf');
const pdfTemplate = require('./documents');
// CORS is to allow access on different domains
app.use(cors());
// parse application/json
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(express.static(path.join(__dirname, "client", "build")));
// TEST ROUTE
app.get("/api", (req, res) => {
res.json({ message: "Hello from server!" });
});
// ALL USERS
app.get("/api/v1", async (req, res) => {
try {
const usersOutput = await db.query(
"select * from users"
);
res.status(200).json({
status: "success",
results: usersOutput.rows.length,
data: {
users: usersOutput.rows,
},
});
} catch (err) {
console.log(err);
}
});
// SINGLE USER
app.get("/api/v1/:id", async (req, res) => {
try {
const userDetailOutput = await db.query(
"select col1, col2 from details psl inner join users pu on psl.user_id = pu.id where pu.auth0_id = $1", [req.params.id]
);
res.status(200).json({
status: "success",
data: {
user_details: userDetailOutput.rows,
},
});
} catch (err) {
console.log(err);
}
});
Related
I have a very simple login system, which takes a username and a password from a user, and when the form is submitted the data is posted to an express http app.
The login function at the react app is as following:
async function login(event){
event.preventDefault();
setRequestState(REQUEST_STATE.pending)
const request = `${SERVER_URL}/login`;
const formData = new FormData();
formData.append("username",data["username"])
formData.append("password",data["password"])
const response = await fetch(request, {
method: 'POST',
body: formData,
enctype:"multipart/form-data",
credentials: 'same-origin',
})
if(!response.ok){
if(response.status === 401){
console.log("username or password are inccorect")
setDisplayError(response.status)
}
if(response.status === 500){
console.log("internal server error")
setDisplayError(response.status)
}
setRequestState(REQUEST_STATE.no_request)
return;
}
setRequestState(REQUEST_STATE.success)
// navigate("/dashboard")
}
the response is successful consistently when the right data is entered.
I use express-sessions to handle sessions, the setup code for the sessions is as following:
const express = require('express');
const cors = require('cors')
const loginRouter = require('./src/routes/login.js');
const session = require('express-session')
const app = express()
app.use(
cors({
origin:true,
credentials:'same-origin',
}))
app.use(session({
secret: 'test',
resave: false,
saveUninitialized: false,
// store: sessionStore,
cookie: {
secure: false,
sameSite: 'none',
}
}));
app.use(express.urlencoded({extended: true}))
app.use('/login', loginRouter)
app.listen(process.env.PORT ,()=>{
console.log(`Server is listening on port ${process.env.PORT}`)
})
login router is as following:
const express = require('express')
const multer = require('multer')
const router = express.Router()
const {getLogin,postLogin, authenticateLogin} = require('../controllers/login')
upload = multer({})
router.post("/", upload.array(0), authenticateLogin, postLogin)
router.get("/", getLogin)
module.exports=router
login controller is as following:
const {pool} = require('../../sqlconfig')
const bcrypt = require('bcrypt');
const postLogin = (req, res) => {
return res.status(200).send({success:true});
}
const getLogin = (req, res) => {
// console.log("get this login betch")
console.log(req.session.id)
if(req.session.userId){
return res.status(200).send({success:true});
}
// console.log("couldn't get login")
return res.status(401).send({success:false});
}
const authenticateLogin = async (req, res, next) => {
const dict = JSON.parse(JSON.stringify(req.body));
const username = dict["username"];
const password = dict["password"];
if(!dict || !username || !password) {
// console.log("Access deneid")
return res.status(401).send({error:"Access denied"});
}
try{
const query = "SELECT passwrd FROM admins WHERE admins.username=?";
const [result] = await pool.execute(query,[username])
if(result.length <= 0){
return res.status(401).send({error:"Access denied"});
}
const passwordInDB = result[0].passwrd;
if(!passwordInDB){
return res.status(401).send({error:"Access denied"});
}
const match = await bcrypt.compare(password, passwordInDB);
// console.log(match)
if(!match){
return res.status(401).send({error:"Access denied"});
}
const queryUserId = "SELECT id FROM admins WHERE admins.username=?";
const [resultUserId] = await pool.execute(queryUserId,[username])
req.session.userId = resultUserId[0].id;
console.log("logged in successfuly!")
console.log(req.session)
next()
}
catch(e){
console.log(e)
}
}
module.exports={
authenticateLogin,
postLogin,
getLogin
}
when login post is called, a session does get created,
and a cookie is sent back to the react application:
Response
but doesn't get saved:
saved cookies
When I run my MERN Stack project on my localhost and get my app's render page, when I click on a button in my app, that button does and displays nothing. When I inspect my client-side render page, I see the following error:polling.js:311 GET http://%22http/socket.io/?EIO=4&transport=polling&t=O7Mtvxd net::ERR_NAME_NOT_RESOLVED. I don't know what it means, I searched the meaning on the internet but without success. Here is my backend index.js file:
const express = require('express')
const cors = require('cors')
const mongoose = require('mongoose')
require("dotenv").config()
const app = express()
const http = require('http')
const server = http.createServer(app)
const io = require('socket.io')(server)
const UserRoutes = require('./routes/User')
const AuthRoutes = require('./routes/Auth')
const PostRoutes = require('./routes/Post')
const PORT = process.env.PORT || 5000
const {MONGODB_URI} = require("./config")
app.use(cors())
app.use(express.json())
app.use((req, res, next) => {
io.req = req
req.io = io
next()
})
app.use('/api/auth', AuthRoutes)
app.use('/api/user', UserRoutes)
app.use('/api/post', PostRoutes)
require('./socket')(io)
mongoose
.connect(MONGODB_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
})
.then(() => {
console.log('database connected')
server.listen(PORT, () => console.log(`server started on port ${PORT}`))
})
.catch((err) => console.log(err))
my backend socket.js file :
const User = require('./models/User')
const jwt = require('jsonwebtoken')
module.exports = (io) => {
io.on('connection', (socket) => {
if (io.req) {
socket.broadcast.emit('friend-login-status', { user_id: io.req.userId })
addSocketIdInDB(socket.id, io.req.userId)
socket.on('disconnect', () => {
socket.broadcast.emit('friend-logout-status', {
user_id: io.req.userId,
})
io.req.userId = null
})
}
})
}
async function addSocketIdInDB(socket_id, user_id) {
const user = await User.findById(user_id)
if (socket_id) {
user.socketId = socket_id
}
await user.save()
}
I looked on this question after this but without success. I work on Microsoft Edge .
controller/product.controller.js this is the controller class
const Product = require('../models/product.model');
//Simple version, without validation or sanitation
exports.test = function (req, res) {
res.send('Greetings from the Test controller!');
};
exports.product_create = function (req, res) {
const product = new Product(
{
name: req.body.name,
price: req.body.price
}
);
product.save(function (err) {
if (err) {
return next(err);
}
res.send('Product Created successfully')
})
};
models/product.model.js
var mongoose = require('mongoose');
const Schema = mongoose.Schema;
const ProductSchema = new Schema({
name: {type: String, required: true, max: 100},
price: {type: Number, required: true},
});
exports.product_details = function (req, res) {
Product.findById(req.params.id, function (err, product) {
if (err) return next(err);
res.send(product);
})
};
exports.product_delete = function (req, res) {
Product.findByIdAndRemove(req.params.id, function (err) {
if (err) return next(err);
res.send('Deleted successfully!');
})
};
exports.product_update = function (req, res) {
Product.findByIdAndUpdate(req.params.id, {$set: req.body}, function (err, product) {
if (err) return next(err);
res.send('Product udpated.');
});
};
router.put('/:id/update', product_controller.product_update);
// Export the model
module.exports = mongoose.model('Product', ProductSchema);
product.route.js this is used to route
const express = require('express');
const router = express.Router();
// Require the controllers WHICH WE DID NOT CREATE YET!!
const product_controller = require('../controllers/product.controller');
router.post('/create', product_controller.product_create);
// a simple test url to check that all of our files are communicating correctly.
router.get('/test', product_controller.test);
router.put('/:id/update', product_controller.product_update);
router.delete('/:id/delete', product_controller.product_delete);
module.exports = router;
app.js this is the app.js
const express = require('express');
const bodyParser = require('body-parser');
const product = require('./routes/product.route'); // Imports routes for the products
const app = express();
// Set up mongoose connection on mongoAtlas
//https://codeburst.io/writing-a-crud-app-with-node-js-and-mongodb-e0827cbbdafb
const mongoose = require('mongoose');
const dev_db_url = 'mongodb://someuser:abcd1234#ds123619.mlab.com:23619/productstutorial';
const mongoDB = process.env.MONGODB_URI || dev_db_url;
mongoose.connect(mongoDB);
mongoose.Promise = global.Promise;
const db = mongoose.connection;
db.on('error', console.error.bind(console, 'MongoDB connection error:'));
app.use('/products', product);
app.listen(3000,function () {
console.log("Server listen on port: 3000");
});
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use('/products', product);
So this is the code of the project and please add scripts "start": "node app.js". This will directly be able to use this and update,insert and delete data is also given here with the code.
The setup looks good, However I noticed few points you might missed in app.js. I believe the following slightly modified setup will connect your mongodb properly:
const mongoose = require('mongoose');
const express = require('express');
var cors = require('cors');
const bodyParser = require('body-parser');
const product = require('./routes/product.route'); // Imports routes for the products
const API_PORT = 3000;
const app = express();
app.use(cors());
// Set up mongoose connection on mongoAtlas
//https://codeburst.io/writing-a-crud-app-with-node-js-and-mongodb-e0827cbbdafb
const dev_db_url = 'mongodb://someuser:abcd1234#ds123619.mlab.com:23619/productstutorial';
// connects our back end code with the database
mongoose.connect(process.env.MONGODB_URI || dev_db_url, { useNewUrlParser: true });
let db = mongoose.connection;
db.once('open', () => console.log('connected to the database'));
// checks if connection with the database is successful
db.on('error', console.error.bind(console, 'MongoDB connection error:'));
// bodyParser, parses the request body to be a readable json format
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// append /api for our http requests
app.use('/product', product);
// launch our backend into a port
app.listen(API_PORT, () => console.log(`LISTENING ON PORT ${API_PORT}`));
mongoose.connect(url, (err) => {
if (!err) {
app.listen(PORT, () => {
console.log('SERVER WORKING');
})
}
})
I am having some trouble with get the param from the url. I use Express(4.16.3) on the server side, and using Axios to make the request. But I couldn't seem to get the param from the url in Express.
Here is my code:
on my Route.js in Express
app.get('/api/surveys/:surveyId', (req, res, next) => {
var id = req.params.surveyId;
console.log(req.params);
// it gets params {surveyId: ':surverId'}
res.send('Hello World');
});
so instead of getting the actual id, it logs params: {surveyId: ':surveyId'}. I have been researching, but seems this is the correct way to do it. I also use axios to make the request:
in actions/index.js (I use react):
export const fetchOneSurvey = () => async dispatch => {
const res = await axios.get('/api/surveys/:surveyId');
dispatch({ type: FETCH_ONE_SURVEY, payload: res.data });};
Not sure if this is relevant:
On the view page, instead of having http://localhost:3000/api/surveys/:surveyId, I have http://localhost:3000/surveys/:surveyId route set in React. When I go to http://localhost:3000/surveys/:surveyId, it does console log (req.params) like I write in express, but I only get a string ':surveyId' is the params, not the actual id on the url.
Please anyone can help me? I have tried many different ways, but nothing seem working. I thank you all very much in advance.
===== Extra section ======
Here is my index.js:
const express = require('express');
const mongoose = require('mongoose');
const cookieSession = require('cookie-session');
const passport = require('passport');
const bodyParser = require('body-parser');
const keys = require('./config/keys');
require('./models/User');
require('./models/Survey');
require('./services/passport');
mongoose.connect(keys.mongoURI);
const app = express();
app.use(bodyParser.json());
app.use(
cookieSession({
maxAge: 30 * 24 * 60 * 60 * 1000,
keys: [keys.cookieKey]
})
);
app.use(passport.initialize());
app.use(passport.session());
require('./routes/authRoutes')(app);
require('./routes/billingRoutes')(app);
require('./routes/surveyRoutes')(app);
if (process.env.NODE_ENV === 'production') {
app.use(express.static('client/build'));
const path = require('path');
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
});
}
My survey model route js:
const _ = require('lodash');
const Path = require('path-parser');
const { URL } = require('url');
const mongoose = require('mongoose');
const requireLogin = require('../middlewares/requireLogin');
const requireCredits = require('../middlewares/requireCredits');
const Mailer = require('../services/Mailer');
const surveyTemplate = require('../services/emailTemplates/surveyTemplate');
const Survey = mongoose.model('surveys');
module.exports = app => {
app.get('/api/surveys', requireLogin, async (req, res) => {
const surveys = await Survey.find({ _user: req.user.id }).select({
recipients: false
});
res.send(surveys);
});
app.get('/api/surveys/:surveyId/:choice', (req, res) => {
res.send('thanks for voting');
});
app.get('/api/surveys/:surveyId', (req, res, next) => {
var id = req.params.surveyId;
console.log(id);
// it gets params {surveyId: ':surverId'}
res.send('Hello World');
});
app.post('/api/surveys/webhooks', (req, res) => {
// console.log(req.body);
// res.send({});
const p = new Path('/api/surveys/:surveyId/:choice');
const test = _.chain(req.body)
.map(({ email, url }) => {
const match = p.test(new URL(url).pathname);
if (match) {
return {
email,
surveyId: match.surveyId,
choice: match.choice
};
}
})
.compact()
.uniqBy('email', 'surveyId')
.each(({ surveyId, email, choice }) => {
Survey.updateOne(
{
// have to add _ to keys as mongoDB rule, mongoose doensn't need.
_id: surveyId,
recipients: {
$elemMatch: { email: email, responded: false }
}
},
{
$inc: { [choice]: 1 },
$set: { 'recipients.$.responded': true },
lastResponded: new Date()
}
).exec();
})
.value();
console.log(test);
res.send({});
});
app.post('/api/surveys', requireLogin, requireCredits, async (req, res) => {
const { title, subject, body, recipients } = req.body;
const survey = new Survey({
// map(email => ({ email }) === map(email =>{ return {email: email}})
title,
body,
subject,
recipients: recipients
.split(',')
.map(email => ({ email: email.trim() })),
_user: req.user.id,
dateSent: Date.now()
});
// send an email
const mailer = new Mailer(survey, surveyTemplate(survey));
try {
await mailer.send();
await survey.save();
req.user.credits -= 1;
const user = await req.user.save();
res.send(user);
} catch (err) {
res.status(422).send(err);
}
});
};
Posting below details for debugging the issue
Note: if you are using Windows OS, use command prompt for node project development. i have seen people using git bash for doing node project developments and it causes unnecessary issues
Below are the steps for debugging
1.Create a new directoryforexample test and initialize it using npm init
2.Install express npm install --save express
3.Create a new file for example index.js and use below code
test/index.js
var express= require("express");
var app = express();
app.get("/api/surveys/:surveyId",(req,res,next)=>{
console.log(req.params.surveyId);
res.send('Hello World');
});
var server= app.listen(3000,()=>{
console.log("port started at ",server.address().port);
})
4.Start the program node index.js
5.Trigger http request from browser http://localhost:3000/api/surveys/llads . The value llads can be accessed using the path param surveyId in the route
6.if you can see the below output in node console then the program is working as it should. And this has to work as described here.
if above steps yields expected output then i don't see any problem in your route code.
Let me know your feedback.
I'm very new to development and working my way through this MEAN tutorial:
MEAN Stack Front To Back [Part 3] - User Model & Register
I've read a few questions on here but can't find a relevant answer.
Here is the primary error code:
Server started on port 3000
Database Error MongoError: failed to connect to server [localhost:27017]
on first connect
TypeError: User is not a constructor
at router.post (/Users/user/Desktop/Development/meanauthapp/routes/users.js:12:16)
Which is odd, because my mongod terminal states this:
2017-03-15T09:52:49.306-0700 I NETWORK
[thread1] waiting for connections on port 27017
2017-03-15T09:52:54.514-0700 I NETWORK
[thread1] connection accepted from 127.0.0.1:49188 #1 (1 connection now open)
2017-03-15T09:52:54.515-0700 I NETWORK
[conn1] received client metadata from 127.0.0.1:49188 conn1:
{ application: { name: "MongoDB Shell" },
driver: { name: "MongoDB Internal Client", version: "3.4.1" },
os: { type: "Darwin", name: "Mac OS X", architecture: "x86_64", version: "15.6.0" } }
/routes/users.js
/*---------------Dependencies-------------*/
const express = require('express');
const router = express.Router();
const User = require('../config/database');
const passport = require('passport')
const jwt = require('jsonwebtoken');
/*----------------------------------------*/
/*---------------Register-----------------*/
router.post('/register', (req, res, next) => {
let newUser = new User({
name: req.body.name,
email: req.body.email,
username: req.body.username,
password: req.body.password
});
User.addUser(newUser, (err, user) => {
if(err) {
res.json({success: false, msg:'Failed to register user'});
} else {
res.json({success: true, msg: 'User Registered'})
}
});
});
/*----------------------------------------*/
/*---------------Authenticate---------------*/
router.post('/authenticate', (req, res, next) => {
res.send('AUTHENTICATE')
});
/*----------------------------------------*/
/*-----------------Profile------------------*/
router.get('/profile', (req, res, next) => {
res.send('PROFILE')
});
/*----------------------------------------*/
module.exports = router;
The line with error is : let newUser = new User({
/config/database.js
module.exports = { database: "mongodb://localhost:27017/famjam",
secret : "yoursecret" }
/models/users.js
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
const config = require('../models/database');
/*User Scheme*/
const UserScheme = mongoose.Scheme({
name: {
type: String
},
email: {
type: String,
required: true
},
username: {
type: String,
required: true
},
password: {
type: String,
required: true
}
});
const User = module.exports = mongoose.model('User', UserScheme);
module.exports.getUserById = function(id, callback) {
User.findById(id, callback);
}
module.exports.getUserbyUsername = function(username, callback) {
const query = {username: username}
User.findOne(query, callback);
}
module.exports.addUser = function(newUser, callback) {
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(newUser.password, salt, (err, hash) => {
if(err) throw err;
newUser.password = hash;
newUser.save(callback);
})
});
}
app.js
/*---------------Dependencies-------------*/
const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const cors = require('cors');
const passport = require('passport');
const mongoose = require('mongoose');
const users = require('./routes/users')
const config = require('./config/database')
/*----------------------------------------*/
/*---------------Database-------------*/
mongoose.connect(config.database);
mongoose.connection.on('connected', () => {
console.log('connected to database ' +config.database)
});
mongoose.connection.on('error', (err) => {
console.log('Database Error '+err)
});
/*----------------------------------------*/
/*------------------App-------------------*/
const app = express();
// Port Number
const port = 3000;
app.listen(port, () => {
console.log('Server started on port '+port)
});
//CORS Middleware
app.use(cors());
// Body Parser Middelware
app.use(bodyParser.json())
// Set Static Folder
app.use(express.static(path.join(__dirname, 'public')));
app.use('/users', users)
/*----------------------------------------*/
/*---------------Index Route--------------*/
app.get('/', (req, res) => {
res.send('Invalid Endpoint')
});
app.get('/myaccount', (req,res) =>{
res.render('myaccount')
})
If your req.body is an object having name, email, username and password set, you should be able to create a new User simply doing:
let newUser = new User(req.body);
You get this error since you are passing to the constructor an object having 4 different attributes, while it expect to receive a request body.