Cant get the data from form post to nodeJS server - node.js

I am trying to write a login page . i got the html page with the login box
im enter email and password than submit to server , on server i got route who get the data check on db if doc exists , if its exists should redirect to main page
the problem is the data i send from form to server always undefined i check here on other ppl questions and i didnt find any good result for this
html login page :
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="/css/style.css" />
<title>{{PageTitle}}</title>
</head>
<body>
{{> header}}
<div class="login-box">
<div class="form">
<form action="/get_user" method="post" class="login-form">
<input type="email" name="Email" placeholder="Email"/>
<input type="password" name="Password" placeholder="Password"/>
<button type="submit">login</button>
</form>
</div>
</div>
{{> footer}}
</body>
server code :
const _ = require('lodash');
const express = require('express');
const bodyParser = require('body-parser');
const {mongoose} = require('./db/mongoose');
const hbs = require('hbs');
var {User} = require('./models/user');
var app = express();
app.set('view engine', 'hbs');
const port = process.env.PORT;
hbs.registerPartials(__dirname + '/../views/partials');
app.user(bodyParser.json());
app.use(express.static(__dirname + '/../public'));
app.use(express.static(__dirname + '/../public/images'));
app.use(express.static(__dirname + '/../public/fonts'));
app.listen(port, () => {
console.log(`Started on port ${port}`);
});
app.get('/', (req, res) => {
res.render('login.hbs', {
PageTitle: 'Log In',
ConnectUser: 'Guest'
});
});
app.post('/get_user', (req, res) => {
var body = _.pick(req.body, ['Email , 'Password']);
User.findOne({
Email: body.Email,
Password: body.Password
}).then((user) => {
console.log(body.Email + ' ' + body.Password);
if(!user) {
return res.status(404).send();
}
var fullName = user.First_Name + ' ' + user.Last_Name;
res.redirect('/mainPage', {ConnectUser: fullName});
}).catch((e) => {
res.status(400).send();
});
});
i did few checks and when i call /get_user req.body->var body -> user r empty
the data arnt pass from form to server im also check this route on postman and its work find when i write the body by myself the only problem i can think is the data i send from form arnt send as json and the body parser send only in json format so maybe i need to change the line
app.use(bodyParser.json());
if any 1 can put in the right direction ill appraise that ty.

When using an html form with method post, the data is posted to the server withContent-Type: application/x-www-form-urlencoded instead of JSON.
Json bodyparser will not do anything with that, as its not using JSON format to send the data. See MDN guide under post method.
In your server code, below app.use(bodyParser.json()) add the following:
app.use(bodyParser.urlencoded({extended: true}));
This will add the data onto the request body the way you expect.

Try playing with the form enc-type attribute and see how to configure the bodyparser to get the values you need based on the enc-type.
application/x-www-form-urlencoded
multipart/form-data
https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/enctype

Related

getting error code "cannot GET /admin/add-product"

this is my second question here on stack overflow.
I am currently doing a course on udemy on node.js from "0" to "expert", now keep in mind my carrer as a developer focuses on front-end not back-end or even middle-ware in particular, this is just a course that I payed for because I feel it complements very well my carrer and the topic is of high interest to me.
Now with the problem... We started working with pug and handlebars, previously we were working with express.js. Every since I installed pug and translated one of the pages from the webpage we are building on the course from vanilla html to pug the server is throwing the "cannot GET /admin/add-product". Now I understand this error is based on the logic end of everything cause the server clearly states it's not able to obtain the specific route where the "add-product.html" code is located. Where i'm confused is that the code is the same the teacher has, and in the videos this error won't show up, I tried to put a question as a comment on the course's comment section but it hasn't been answered and this is keeping me from continuing with the material. It would be of great value if someone here would look over the code (which I will be posting in this question) and gives me a hand cause at this point i'm completely lost.
Thanks you very much stack overflow community
Project code:
app.js:
const path = require('path');
const http = require('http');
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.set('view engine', 'pug');
app.set('views', 'views');
const adminData = require('./routes/admin');
const userRoutes = require('./routes/user');
app.use(bodyParser.urlencoded({extended: true }));
app.use(express.static(path.join(__dirname, 'public')));
app.use('/admin', adminData.routes);
app.use(userRoutes);
// app.use((res, req, next) => {
// res.status(404).sendFile(path.join(__dirname, 'views', ''));
// });
const server= http.createServer(app);
server.listen(3000);
admin.js:
const path = require('path');
const express = require('express');
const rootDir = require('../util/path');
const router = express.Router();
const products = [];
router.get('/admin', (req, res, next) => {
res.sendFile(path.join(rootDir, 'views', 'add-product.html'));
});
router.post('/admin', (req, res, next) => {
products.push({title: req.body.title})
res.redirect('/');
});
exports.routes = router;
exports.products = products;
user.js:
const path = require('path');
const express = require('express');
const rootDir = require('../util/path');
const adminData = require('./admin');
const router = express.Router();
router.get('/', (req, res, next) => {
const products = adminData.products;
res.render('shop', {prods: products, docTitle: 'Shop'});
});
module.exports = router;
path.js:
const path = require('path');
module.exports = path.dirname(require.main.filename);
add-product.html:
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Add product page</title>
<link rel="stylesheet" href="/css/main.css">
<link rel="stylesheet" href="/css/product.css">
</head>
<body>
<header class="main-header">
<nav class="main-header__nav">
<ul class="main-header__item-list">
<li class="main-header__item"><a class="active" href="/">SHOP PAGE</a></li>
</ul>
</nav>
</header>
<main>
<form class="product-form" action="/admin/add-product" method="POST">
<div class="form-control">
<label for="title">Title</label>
<input type="text" name="title" id="title">
</div>
<button type="submit">ADD PRODUCT</button>
</form>
</main>
</body>
</html>
shop.pug:
<!DOCTYPE html>
html(lang="en")
head
meta(charset="UTF-8")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
meta(http-equiv="X-UA-Compatible", content="ie=edge")
title #{docTitle}
link(rel="Stylesheet", href="/css/main.css")
link(rel="Stylesheet", href="/css/products.css")
body
header.main-header
nav.main-header__nav
ul.main-header__item-list
li.main-header__item
a.active(href="/") Shop
li.main-header__item
a(href="/admin/add-product") Add Product
main
.grid
each product in prods
article.card.product-item
header.card__header
h1.product__title #{product.title}
.card__image
img( src="https://www.vecteezy.com/photo/1224769-open-book-on-dark-background", alt=" a book ")
.card__content
h2.product__price $19.99
p.product__description A ver interesting book about so many even more intersting things!
.card__actions
button.btn Add to Cart
Thanks for your time everyone
Not sure, I guess the path of line 11 and 15 in admin.js should be '/add-product' instead of '/admin'. i.e.
router.get('/add-product', (req, res, next) => {
In your code, the only route under /admin is /admin/admin with method GET or POST. You can try GET /admin/admin and see if it's the expected result. if true, that indicates you wrote a wrong path in line 11 and 15 in admin.js
If you want to GET /admin/add-product, you'll need a route in admin.js which path is /add-product, since all request with a path begins with /admin are handled by adminData.routes at line 18 in app.js

How to manage the redirection in express.js?

I know there are plenty of similar questions like my, but I couldn't find any solution for my problem.
I think the issue is that am not getting the product.html and I assume that there is also a problem with the redirection to the product.html.
product.html
<!DOCTYPE html>
<html>
<head>
<title>Product</title>
<meta charset="utf-8" />
</head>
<body>
<form id="product" action="/information" method="POST">
<label for="product_id">Enter product ID: </label>
<input id="product_id" name="product_id" type="text" required />
<input type="submit" />
</form>
</body>
</html>
index.js
const express = require("express");
// load data
const products = require("./data.json");
const app = express();
// static files
app.use(express.static("public"));
// form middleware
app.use(express.urlencoded({ extended: true }));
app.post("/information", (req, res) => {
// ES6 deconstruction syntax, get user input
const { product_id } = req.body;
// search product array
const product = products.find((product) => product.Product_ID === product_id);
if (product) res.json(product);
else res.send("product not found");
});
// redirect all GET requests to product form
app.get("*", (req, res) => {
res.redirect("/product.html");
});
app.listen(8000,console.log(`App listening at http://localhost:8000`));
When I run the code like above, I get the following error: The page isn’t redirecting properly
(Cookies & Cache is deleted). I even tried another project with a node.js server and the localhost in Firefox worked.
When I command the redirection out, I get this error: Cannot GET /
When I use "/" instead of "*" in the redirections, this error appears: Cannot GET /product.html
I don't understand why it doesn't get the product.html and why the redirection doesn't work right.
To render product.html for every endpoint, you can use sendFile rather than redirect, you will need to use path module, which is a core module to resolve the path to html file:
const path = require('path');
//your code
app.get('*', (req, res)=> {
//note that product.html file is in the same directory or you specify
//its relative path
res.sendFile(path.resolve(__dirname, 'product.html'))
})

Cannot POST (node/express), what am I missing?

I'm trying to use a simple POST request with Node using Express and instead am getting cannot POST with a 404. In the end I want to use ajax so it POSTs without refreshing the page in the browser, but first I need to get it running like this and I can't figure out what I've gotten wrong.
public/form.html
<!DOCTYPE html>
<form method="POST" action="">
<input name="firstName">
<input name="lastName">
<input type="submit">
</form>
app.js
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: false }));
//server running?
app.listen(3000,() => {
console.log('Started on PORT 3000');
})
//Serve the web page directory
app.use(express.static('./public'))
//Return form fields
app.post('form.html', (req, res) => {
console.log("First name: " + req.body.firstName)
console.log("Last name: " + req.body.lastName)
res.end()
})
app.post("/api", (req, res) => {
console.log("First name: " + req.body.firstName);
console.log("Last name: " + req.body.lastName);
res.end();
});
Here you have to make POST request to /api
<form method="POST" action="/api">
I've figured it out and will share in case others are looking for the same thing. The other responses are correct, but I was looking to POST without changing the URL. This doesn't look to be possible because I always get cannot POST and a 404 if I point to the existing page (either leaving action empty or using "#").
However, when you use AJAX, you still point to a new URL with the form action attribute and in your node app, but your AJAX code will keep the URL on the same page (the page doesn't refresh).

Uploading file with express-fileupload

I am trying to upload a file with express-fileupload and am having no luck getting it to work. I can get the file (in this case an image) to 'upload' in the sense that I can get the console to show an image uploaded with the correct folder.
startup.js
router.get('/upload', function(req, res) {
res.render('upload');
});
router.post('/upload', function(req, res) {
// The name of the input field (i.e. "sampleFile") is used to retrieve the uploaded file
let startup_image = req.files.image;
// Use the mv() method to place the file somewhere on your server
startup_image.mv('/images' , function(err) {
if (err) {
console.log(err);
}
});
});
Then my html form is
<form ref='uploadForm'
id='uploadForm'
action='/upload'
method='post'
encType="multipart/form-data">
<input type="file" name="image" />
<input type='submit' value='Upload!' />
</form>
You are pointing the directory where the file would go to, but you are not giving it a file name. I would say let the user decide the file name for the client side and add it to the path.
<input name="userFileName" type="text">//userFilename Here</input>
var myFILENAME = req.body.userFilename
startup_image.mv('/images/'+myFILENAME+'.jpg', ..) //myFILENAME needs to be added here
Also please see Full Example in how to upload files with express-fileupload
UPDATE
I found solution to your problem you need to add __dirname to this line which will let the program know your current directory to your source code.
startup_image.mv(__dirname + '/images' , function(err) {..
UPDATE 2
Here is my source code, if you want you can try it with this.
my html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<form ref='uploadForm' encType="multipart/form-data" class="" action="/upload" method="post">
<input type="text" name="fileName" value=""><br>
<input type="file" name="foo" value=""><br>
<input type="submit" name="" value="upload!">
</form>
</body>
</html>
my main source
var express = require("express);
var app = express();
const fileUpload = require('express-fileupload');
//npm install ejs, express, express-fileupload
//middleware
app.use(express.static(__dirname));
app.set('view engine', 'ejs');
app.use(fileUpload());
app.get('/inputFile', function(req, res){
res.render('inputt');
});
app.post('/upload', function(req, res) {
// The name of the input field (i.e. "sampleFile") is used to retrieve the uploaded file
var startup_image = req.files.foo;
var fileName = req.body.fileName;
// Use the mv() method to place the file somewhere on your server
startup_image.mv(__dirname + '/images/' + fileName + '.jpg' , function(err) {
if(err){
console.log(err);
}else{
console.log("uploaded");
}
});
});
app.listen(7777);
using async/await style
in your server file do this
const fileUpload = require('express-fileupload');
app.use(
fileUpload({
limits: { fileSize: 50 * 1024 * 1024 },
useTempFiles: true,
// dir for windows PC
tempFileDir: path.join(__dirname, './tmp'),
}),
);
then in your controllers, do this
const file = req.files.filename;
await file.mv(file.name);
if (!file || Object.keys(req.files).length === 0) {
return res.status(400).console.error('No files were uploaded.');
}
This solution is for non ejs and exporting modules solution:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>File Upload</title>
</head>
<body>
<form ref='uploadForm' encType="multipart/form-data" class="" action="/path/to/nodejs/upload/file" method="post">
<input type="file" name="my_file"><br>
<input type="submit" name="" value="upload">
</form>
</body>
</html>
Now here is the NodeJS
const express = require("express");
const app = express();
const fileUpload = require('express-fileupload');
app.use(fileUpload({ safeFileNames: true, preserveExtension: true }))
app.post('/', function(req, res) {
// The name of the input field (i.e. "sampleFile") is used to retrieve the uploaded file
let the_file = req.files.my_file;
the_file.mv('/path/to/html/uploads/up/' + the_file.name , function(err) {
res.writeHead(200, {"Content-Type": "text/plain"});
if(err){
console.log(err);
res.write(err);
res.end();
} else {
console.log("uploaded");
res.write("upload of file "+the_file.name+" complete");
res.end();
}
});
});
module.exports = app;
You have to create folder images!
//install path module
const path = require('path');
// remaining code
let startup_image = req.files.image;
startup_image.mv(path.resolve(__dirname,'/images',startup_image.name), function(error){
//remaining code
})
this way
file.mv(path.resolve(__dirname, '../public/images', filename)

router.get not posting multiple params

Hi so I am learning basics of node.js and express, and I was trying to submit a form with two parameters and trying to get that in the same screen.
But for some reason I guess I am not sure how to use router.get to get the both input fields parameters.
Here is my js file
var express = require('express');
var router = express.Router();
router.get('/:awesomeTitle?/:awesomeAuthor?', function(req, res, next) {
res.render('node',
{title: req.params.awesomeTitle ? req.params.awesomeTitle : '' , author: req.params.awesomeAuthor ? req.params.awesomeAuthor : '' });
});
router.post('/', function(req, res, next) {
var awesomeTitle = req.body.title;
var awesomeAuthor = req.body.author;
res.redirect('/' + awesomeTitle + awesomeAuthor);
});
module.exports = router;
And here is my hbs file.
<h1> Result </h1>
<h2>{{author}}</h2>
<h1>{{title}}</h1>
<form action="/" method="post">
<input type="text"/ name="title">
<input type="text"/ name="author">
<button type="submit">Submit</submit>
</form>
So just wanted to know how to get the awesome title and author from submit to the page again in the h1 and h2 tags.
P.S I am not sure how to debug this application so.. and it doesn't show any errors, all I get is both the input fields answer combined.
It looks like you're missing a / in your redirect. Try changing the last line in your post handler to this:
res.redirect('/' + awesomeTitle + '/' + awesomeAuthor);

Resources