NodeJS express Post form - action always 404 - javascript

No matter what link I declare in the action of my form, it always returns an 404 error. if I change the method to get, it doesn't.
I want to use post because i'm trying to get the data from my input fields and post it in my mongedb database:
HTML:
<form class="container-fluid searchContainer" action="/active" method="post">
<div class="col-xs-6">
<div class="form-group">
<label for="businessUnit">Business unit</label>
<input type="text" ng-model="businessUnit" id="businessUnit" name="businessUnit" class="form-control"/>
</div>
<div class="form-group">
<label for="tenderId">Tender ID</label>
<input type="text" name="tenderID" ng-model="tenderId" id="tenderId" class="form-control"/>
</div>
</div>
<div class="col-xs-6">
<div class="form-group">
<label for="tenderDate">Tender Bidding Date</label>
<input type="date" ng-model="tenderDate" name="tenderDate" id="tenderDate" class="form-control"/>
</div>
<div class="form-group">
<label for="therapyArea">Therapy area</label>
<input type="text" ng-model="therapyArea" name="therapyArea" id="therapyArea" class="form-control"/>
</div>
</div>
<div class="col-md-12 text-right">
<input type="submit" id="btnCreate" value="Create" class="btn btn-primary" >
</div>
</form>
JAVASCRIPT:
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var routes = require('./routes/index');
var users = require('./routes/users');
var active = require('./routes/active');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
app.use('/active', active);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/tenders');
var db = mongoose.connection;
db.on('error', function(err) {
console.log('connection error', err);
});
db.once('open', function() {
console.log('connected.');
});
var Schema = new mongoose.Schema({
TenderID: String,
TenderDate: String,
BusinessUnit: String,
TherapyUnit: String
});
var Tender = mongoose.model('Tender', Schema);
app.post('/active', function(req, res) {
new Tender({
TenderID: req.body.tenderID,
TenderDate: req.body.tenderDate,
BusinessUnit: req.body.businessunit,
TherapyUnit: req.body.therapyUnit
}).save(function(err, doc) {
if (err) res.json(err);
else res.send('Succesfully insterted')
})
});

Because you define your 404 route handler before you define app.post('/active'), express evaluates the 404 rule first and returns it. Your POST /active route never gets evaluated. To fix this you need to give Express your POST /active route before your 404 route (which should always be your last route).
Unless you have an equivalent POST /active route defined in the file ./routes/active, the line
app.use('/active', active);
won't fix this problem even though it is evaluated before your 404 route. You can read more about app.use() vs app.get|post|etc() in the express docs.
Express evaluates rules in the order they are passed to it via use() or get|post|delete|etc()

You have defined get route in your server. Try to change the
app.get('/active',function(req,res){
into
app.post('/active',function(req,res){
In this way, you will respond to a post request from the browser.

Related

Express res.redirect causing "Uncaught SyntaxError: Unexpected token <"

Using Node.js, Express, Socket.io, firebase admin+auth and Handlebars.
I get the error Uncaught SyntaxError: Unexpected token <
When I used res.redirect('/login'); but it goes when I remove res.redirect have tried including the redirect type (301) changing the path to ../login /../login but still has the error?
Really stumped on this one any help would be great!
Seems most other discussions about it stay it's a path issue?
Imports
const express = require('express');
const app = express();
const http = require('http').createServer(app);
const io = require('socket.io')(http);
var exphbs = require('express-handlebars');
Code that I think is relavent
// Express and Handlebars
app.engine('handlebars', hbs.engine);
app.set('view engine', 'handlebars');
Main issue code
// show login page before middleware check (works fine)
app.get('/login', (req, res) => {
res.render('login', {
showTitle: true,
title: 'Login'
});
});
// Auth Check All Pages HERE Catches access to all other pages
// Main Issue
app.use(function(req, res, next) {
console.log('[firebase.auth()] ', firebase.auth().currentUser);
if(firebase.auth().currentUser === null){
res.redirect('/login');
return; // same problem without return
}else{
next();
}
});
// all other routes...
is express.staticcausing it?
app.use(express.static('/public'));
const port = 3000;
http.listen(port, () => console.log(`Example app listening on port ${port}!`))
login.handlebars
{{#if showTitle}}
<h1>{{title}}</h1>
{{/if}}
<form id="login" >
<label for="email">Email Address</label>
<input id="email" type="email" value="ben#bnr.io"/>
<label for="pass">Password</label>
<input id="pass" type="password"/>
<button>Login</button>
</form>
The error was caused by the res.redirect('/login'); redirecting scripts in the public folder, so the scripts src js/client.js would be redirected to /login.
It's because of the middleware app.use(function(req, res, next) fires on all HTTP requests.
The Fixed Changed it to using a function on the routes instead:
Example:
app.get('/', isAuthenticated, (req, res) => {
res.render('home', {
showTitle: true,
title: 'Home'
});
});
Function:
function isAuthenticated(req, res, next) {
if (uid)
return next();
// IF A USER ISN'T LOGGED IN, THEN REDIRECT THEM
res.redirect('/login');
}

Error: Can't set headers after they are sent. authentication system

I want to write a little authentication app with mysql connection and I get this error all the time, but I need it this way.
I want to send a response if the client gets /admin if he is not an admin and if he is, admin should be rendered.
app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var index = require('./routes/index');
const admin = require("./routes/admin");
const session = require("express-session");
var app = express();
app.set("trust proxy", 1);
app.use(session({
secret: "asdf",
resave: false,
cookie: {
maxAge: 120000
},
saveUninitialized: false
}));
function checkIfLoggedin(req,res,next){
if(!(req.originalUrl === "/") && !req.session.loggedIn){
res.redirect('/');
return;
}
next();
};
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(checkIfLoggedin);
app.use('/', index);
app.use("/admin", admin);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// 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;
index.js
var express = require('express');
var router = express.Router();
const bcrypt = require('bcrypt-nodejs');
var dbPassword;
import mysql from "mysql";
//
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', {});
});
router.post('/', function(req,res,next) {
console.log("1");
const enteredUsername = req.body.username;
const enteredPassword = req.body.password;
const con = mysql.createConnection({
host: "localhost",
user: "user",
password: "pass",
database: "db"
});
con.query('SELECT * FROM users WHERE username = ?;', [`${enteredUsername}`], (error, results, fields) => {
if (results.length > 0) {
console.log("2");
console.log(error);
let dbPassword = results[0].password;
bcrypt.compare(enteredPassword, dbPassword, (err,response) => {
console.log(err);
console.log(response);
console.log("3");
if (response == true) {
req.session.user = {
userId: results[0].userId,
username: results[0].username,
isAdmin: results[0].isAdmin,
};
req.session.loggedIn = true;
console.log("file");
if (req.session.user.isAdmin) {
res.redirect("/admin");
}
else{
res.redirect("/file/" + req.session.user.userId);
}
}
else{
req.session.loggedIn = false;
console.log("false");
res.send("Wrong password");
}
});
}
else{
res.send("Wrong Data");
}
});
});
module.exports = router;
admin.js
var express = require('express');
var router = express.Router();
/* GET users listing. */
router.get('/', function(req, res, next) {
if (!req.session.user.isAdmin) {
res.send("Du bist kein Admin!");
}
res.render("admin");
});
module.exports = router;
index.ejs
<!DOCTYPE html>
<html>
<head>
<title>Costufi</title>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link type="text/css" rel="stylesheet" href="stylesheets/materialize.min.css" media="screen,projection"/>
</head>
<body>
<main>
<center>
<div class="container">
<div class="z-depth-2" style="display: inline-block; padding: 20px 50px 10px 50px; margin-top: 15%;">
<form class="col s12" action="/" method="post">
<div class="row">
<h4>Login</h4>
<div class="input-field col s12">
<input type="text" name="username" id="username" class="validate">
<label for="username">Username</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
<input type="password" name="password" id="password" class="validate">
<label for="password">PassworD</label>
</div>
</div>
<div class="row">
<button class="left btn waves-effect waves-light indigo darken-2" type="submit" name="send">Login
<i class="material-icons right">send</i>
</div>
</form>
</div>
</div>
</center>
</main>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script type="text/javascript" src="js/materialize.min.js"></script>
</body>
</html>
This error is caused when you attempt to send more than one response to the same request. I didn't study all the places in your code, but here's one obvious case:
/* GET users listing. */
router.get('/', function(req, res, next) {
if (!req.session.user.isAdmin) {
res.send("Du bist kein Admin!");
}
res.render("admin");
});
If your if test is true, then you end up doing both a res.send() and a res.render(). The res.render() triggers the warning because you've already sent a response on this connection and can't send another one. You should change it to this:
/* GET users listing. */
router.get('/', function(req, res, next) {
if (!req.session.user.isAdmin) {
res.send("Du bist kein Admin!");
} else {
res.render("admin");
}
});

Express.js routers post request returns 404

My express server returns 404 error when i try to send request from html form. However get request works fine. I have separated files for server and routes. I can't make requests in app.js, because there are too many of them (for different pages). I want to make post-insert request to db, but i just can't get any information from my form.
Is there something i missing?
my html form (ejs precisely)
<form action="/add" method="POST">
<input type="text" name="title" placeholder="Event name" />
<input type="text" name="subcategory" placeholder="Category" />
<input type="text" name="date" placeholder="Date" />
<input type="text" name="place" placeholder="Place" />
<input type="text" name="organisator" placeholder="Organisator" />
<textarea name="description" placeholder="Description" onkeyup="adjust_textarea(this)"></textarea>
<input type="submit" value="Add" />
</form>
my App.js file (error on 404 handler)
const express = require('express');
const path = require('path');
const logger = require('morgan');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
var app = express();
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
//db connection
var mysql = require("mysql");
app.use(function(req, res, next){
res.locals.connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : 'mypassword',
database : 'mydb'
});
res.locals.connection.connect();
next();
});
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', require('./routes/index'));
app.use('/events', require('./routes/events'));
//handling errors
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
app.use(function(err, req, res, next) {
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
res.status(err.status || 500);
res.render('error');
});
//server init
var http = require('http');
var server = http.createServer(app);
server.listen(4000);
if(server.listening){
console.log('Server is listening on port 4000');
}
module.exports = app;
my ./routes/events.js file
const express = require('express');
const router = express.Router();
router.get('/', function (req, res, next) {
let query = '*select query*';
res.locals.connection.query(query, function (error, results, fields) {
if (error) throw error;
res.render('index', { title: 'Events', data: results });
});
});
router.post('/add', function (req, res) {
var obj = req.body.title;
console.log(obj);
res.redirect('/events');
});
What i see in browser
You have the 'add' endpoint listed in in your 'routes/events.js' file, which causes the structure of the final route to be '/events/add.' In your form, you are sending to the '/add' endpoint so to fix the issue, either change the action prop on the form to '/events/add' or move the '/add' endpoint into it's own route like this:
router.post('/add', function(req, res) {
var obj = req.body.title;
console.log(obj);
res.redirect('/events');
});

Req.flash(errors) Not Displaying -NodeJS 5.7.0

I am trying to make it so when a user enters an email that is already in the db to let the user know that that account email is already registered.
I am getting the correct error from mongo db but I dont want to display all that junk. I want it to just display my error on my signup page in the form saying something like "This email address is registered already".
MongoDB Response:
MongoError: E11000 duplicate key error index: jcommerce.users.$email_1 dup key: { : "james12345#gmail.com" }
at Function.MongoError.create (C:\jcommerce\node_modules\mongodb-core\lib\error.js:31:11)
at toError (C:\jcommerce\node_modules\mongodb\lib\utils.js:114:22)
at C:\jcommerce\node_modules\mongodb\lib\collection.js:616:23
at handleCallback (C:\jcommerce\node_modules\mongodb\lib\utils.js:96:12)
at C:\jcommerce\node_modules\mongodb\lib\bulk\unordered.js:470:9
at handleCallback (C:\jcommerce\node_modules\mongodb\lib\utils.js:96:12)
at resultHandler (C:\jcommerce\node_modules\mongodb\lib\bulk\unordered.js:417:5)
at commandCallback (C:\jcommerce\node_modules\mongodb-core\lib\topologies\server.js:936:9)
at Callbacks.emit (C:\jcommerce\node_modules\mongodb-core\lib\topologies\server.js:116:3)
at null.messageHandler (C:\jcommerce\node_modules\mongodb-core\lib\topologies\server.js:282:23)
at Socket.<anonymous> (C:\jcommerce\node_modules\mongodb-core\lib\connection\connection.js:273:22)
at emitOne (events.js:90:13)
at Socket.emit (events.js:182:7)
at readableAddChunk (_stream_readable.js:153:18)
at Socket.Readable.push (_stream_readable.js:111:10)
at TCP.onread (net.js:529:20)
Route Class
var router = require('express').Router();
var User = require('../models/user')
router.get('/signup', function (req, res, next) {
res.render('accounts/signup', {
errors: req.flash('errors')
});
});
router.post('/signup', function(req, res, next) {
var user = new User();
user.profile.name = req.body.name;
user.email = req.body.email;
user.password = req.body.password;
// Validate
User.findOne({email: req.body.email}, function (err, existingUser) {
if (existingUser) {
req.flash('errors', 'Account with that email address already exists');
return res.redirect('/signup');
}
else {
// save user to database
user.save(function(err, user) {
if (err) {
return next(err);
}
return res.redirect('/');
});
}
}); // Mongoose method find one document in db
});
module.exports = router;
EJS
<% layout('layout') -%>
<div class="row">
<div class="col-lg-6 col-md-offset-3">
<% if (errors.length > 0) { %>
<div class="alert alert-danger alert-dismissible">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<%= errors %>
</div>
<% } %>
<form method="post">
<h1> Signup! </h1>
<div class="form-group">
<label="name"> Name: </label>
<input type="text" class="form-control" name="name">
</div>
<div class="form-group">
<label="name"> Email: </label>
<input type="email" class="form-control" name="email">
</div>
<div class="form-group">
<label="name"> Password: </label>
<input type="passwod" class="form-control" name="password">
</div>
<button type="submit" class="btn btn-success"> Submit</button>
</form>
</div>
</div>
Server.js AKA app.js
// Require library we want to use
var express = require('express');
var morgan = require('morgan');
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var ejs = require('ejs');
var engine = require('ejs-mate');
var session = require('express-session');
var cookieParser = require('cookie-parser'); // parses cookies and put it on the request object in the middleware
var flash = require('express-flash');
var User = require('./models/user');
// App is reffering to express objects, bc we want to use express objects
var app = express();
mongoose.connect('mongodbconnectionstring', function (err) {
if (err) {
console.log(err);
}
else
{
console.log("Connected to the database");
}
});
//Middleware - logs requests in cmd
app.use(express.static(__dirname + '/public'));
app.use(morgan('dev'));
app.use(bodyParser.json()); // Express can parse data format
app.use(bodyParser.urlencoded({extended: true}));
app.use(cookieParser());
app.use(session({
resave: true,
saveUninitialized: true,
secret: "James#####"
}));
app.use(flash());
app.engine('ejs', engine)
app.set('view engine', 'ejs');
// body parser takes the body of request and parses it -> Format encoded or raw data
var mainRoutes = require('./routes/main');
var userRoutes = require('./routes/user');
app.use(mainRoutes); // Express is using main routes
app.use(userRoutes);
// Listen on port number 3000 ,
app.listen(3000, function (err) {
if (err) {
throw err;
}
console.log("Server is Running on port 3000");
});
The error stems from this line:
user.email = req.body.email;
This occurs because req.body.email is undefined which means the email is not unique. You should verify that the request to /signup is sent with data from the client.
I just had to check if
exisitinguser !== null
if (existingUser !== null)

Getting response after posting to mongodb

I tried testing my code written to post data to mongodb via postman using x-www-formurlencoded but I keep getting this error:
<!DOCTYPE html>
<html>
<head>
<title></title>
<link rel="stylesheet" href="/stylesheets/style.css">
</head>
<body>
<h1>Not Found</h1>
<h2>404</h2>
<pre>Error: Not Found
at Layer.app.use.res.render.message [as handle] (c:\Users\Tomix\Documents\Source\Tomix\app.js:39:15)
at trim_prefix (c:\Users\Tomix\Documents\Source\Tomix\node_modules\express\lib\router\index.js:226:17)
at c (c:\Users\Tomix\Documents\Source\Tomix\node_modules\express\lib\router\index.js:198:9)
at Function.proto.process_params (c:\Users\Tomix\Documents\Source\Tomix\node_modules\express\lib\router\index.js:251:12)
at next (c:\Users\Tomix\Documents\Source\Tomix\node_modules\express\lib\router\index.js:189:19)
at next (c:\Users\Tomix\Documents\Source\Tomix\node_modules\express\lib\router\index.js:166:38)
at next (c:\Users\Tomix\Documents\Source\Tomix\node_modules\express\lib\router\index.js:150:14)
at next (c:\Users\Tomix\Documents\Source\Tomix\node_modules\express\lib\router\index.js:166:38)
at Function.proto.handle (c:\Users\Tomix\Documents\Source\Tomix\node_modules\express\lib\router\index.js:234:5)
at Layer.router (c:\Users\Tomix\Documents\Source\Tomix\node_modules\express\lib\router\index.js:23:12)</pre>
</body>
<!--Live reload script -->
<script type="text/javascript" src="http://localhost:35729/livereload.js"></script>
</html>
So what am trying to do is to create an e-commerce website with mean stack,so am trying to structure the app files and folder to reflect the server side and the client side.
The code here is to save data to database (mongodb), but from the error message I was able to deduce is that at the point it ought to return response in json format it throws the error message.
exports.create = function(req, res) {
console.log('I got called', req.body);
var product = new Product(req.body);
product.save(function(err) {
if (err) {
return res.send(400, {
message: err
});
} else {
res.json(product);
}
});
};
My app.js file
'use strict';
var express = require('express');
var path = require('path');
var favicon = require('static-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var methodOverride = require('method-override');
var routes = require('./routes/index');
var users = require('./routes/users');
/*connecting the to database*/
require('./config/db');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'app/views'));
app.set('view engine', 'jade');
app.use(favicon());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(methodOverride('X-HTTP-Method-Override'));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
/// catch 404 and forwarding to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
/// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
next();
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
next();
});
//Routes
require('./app/routes/product.server.routes.js')(app);
exports = module.exports = app;
Please am stuck have search online for possible solution, some of the suggestion I got was I need to add method-override to my express configuration.
I think that you missed a part of the equation:
Post/Info -> Connector/Driver -> Mongodb/Database
Yo can not post JSON to mongo via Postma. You'll need to find a mongodb solution for javascript to play with it. You can try it with Node.js for example. Here I give you a list of all the language possibilities to connect to mongo.
http://docs.mongodb.org/ecosystem/drivers/
Hope it helps!

Categories