Node.js/Express post route failing - node.js

Trying out Node.js for the first time. My POST route is failing with "Cannot POST /admin/add-product.html". GET request is being served fine from the same route. I have had a look around here. Several answers to similar issues but nothing is helping. Here is my code:
./index.js
const path = require('path');
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const adminRoutes = require('./src/routes/admin');
const shopRoutes = require('./src/routes/shop');
app.use(bodyParser.urlencoded({ extended: false }));
app.use('/admin', adminRoutes);
app.use(shopRoutes);
app.listen(3000);`
./src/routes/admin.js
const path = require('path');
const express = require('express');
const router = express.Router();
// served on /admin/add-product GET route
router.get('/add-product', (req, res, next) => {
res.sendFile(path.join(__dirname, '../', 'views', 'add-product.html'));
});
// served on /admin/add-product POST route
router.post('/add-product', (req, res, next) => {
console.log(req.body);
res.redirect('/');
// res.send('<h1>product saved</h1>');
});
module.exports = router;
./src/views/add-product.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Add Product</title>
</head>
<body>
<header>
<nav>
<ul>
<li>Shop</li>
<li>Add Product</li>
</ul>
</nav>
</header>
<main>
<form action="/admin/add-product.html" method="POST">
<input type="text" name="title" /><button type="submit">
Add Product
</button>
</form>
</main>
</body>
</html>
Thank you!!!

The action in the form need to match the route declare in the NodeJS application, it should be :
<form action="/admin/add-product" method="POST">

Remove the .HTML from the action attribute of the form.

Related

using express csurf with ajax doesnt work

i am new with node js. i try to use csurf token with express using AJAX. here is my code
from server (app.js)
var cookieParser = require('cookie-parser')
var csrf = require('csurf')
var bodyParser = require('body-parser')
var express = require('express')
// setup route middlewares
var csrfProtection = csrf({ cookie: true })
var parseForm = bodyParser.urlencoded({ extended: false })
// create express app
var app = express()
app.set('view engine', 'ejs')
app.set('views', 'views')
// parse cookies
// we need this because "cookie" is true in csrfProtection
app.use(cookieParser())
app.use(express.static(__dirname + '/public'));
app.get('/form', csrfProtection, function (req, res) {
// pass the csrfToken to the view
res.render('send', { csrfToken: req.csrfToken() })
})
app.post('/process', parseForm, csrfProtection, function (req, res) {
console.log(req.body.name); // <--- it is doesnt show in my terminal
res.send('data is being processed')
})
app.listen(3000);
HTML (send.ejs)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="csrf-token" content="<%=csrfToken%>">
<title>Document</title>
</head>
<body>
<form>
<input type="text" name="name" value="Jhon Doe" class="inp-name">
<input type="submit" value="Send" class="btn-send">
</form>
<script src="/javascripts/script.js"></script>
</body>
</html>
JS file (script.js)
document.querySelector('.btn-send').addEventListener('click',
() => {
const name = document.querySelector('.inp-name').value;
// Read the CSRF token from the <meta> tag
const token = document.querySelector('meta[name="csrf-
token"]').getAttribute('content')
// Make a request using the Fetch API
fetch('/process', {
credentials: 'same-origin', // <-- includes cookies in the request
headers: {
'CSRF-Token': token // <-- is the csrf token as a header
},
method: 'POST',
body: {
name: name
}
})
});
when i try to run this i think it doesnt work because when i see in my terminal the name of Jhon Doe doesnt appears.
i try this example from this site http://expressjs.com/en/resources/middleware/csurf.html

Why empty req.body on POST request in expressjs?

I am new to expressjs. I am sending data from a web form to another form(or show on console) with the POST request. But I am receiving a empty object. My routes are in separate folder where i handling the data. I used body-parser as middleware for handling the request body.
This is a simple webform
<!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">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB" crossorigin="anonymous">
<title>Login</title>
</head>
<body>
<div class="container">
<div class="jumbotron">
<h1>Login</h1>
</div>
<form method="POST" class="col-md-8" action="/profile">
<div class="form-group row">
<div class="col-md-4">
<label for="email" class="form-control border-0">Email</label>
</div>
<div class="col-md-8">
<input type="email" class="form-control" id="email" placeholder="Enter email">
</div>
</div>
<div class="form-group row">
<div class="col-md-4">
<label for="password" class="form-control border-0">Password</label>
</div>
<div class="col-md-8">
<input type="password" class="form-control" id="password" placeholder="Enter Password">
</div>
</div>
<button type="submit" class="btn btn-primary">Login</button>
</form>
</div>
</body>
</html>
This is the route file(route.js)
var express = require('express');
var router = express.Router();
var bodyParser = require('body-parser');
var jsonParser = bodyParser.json(); // support json encoded bodies
var urlencodedParser = bodyParser.urlencoded({ extended: false }); // support encoded bodies
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index');
});
router.get('/login', (req, res)=>{
res.render('auth/login');
});
router.post('/profile', urlencodedParser, function(req, res){
res.send("THank you");
console.log("called post");
console.log(req.body);
});
module.exports = router;
This is app.js
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var bodyParser = require('body-parser');
var jsonParser = bodyParser.json(); // support json encoded bodies
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
app.use('/users', usersRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
You need to put name attribute to HTML <input> tag, for ex:
<input name="email" type="email" class="form-control" id="email" placeholder="Enter email">

Multer while getting error " transfer-encoding' of undefined"

HTML
<!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">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/css/materialize.min.css">
<title>Node file uploads</title>
</head>
<body>
<div class="container">
<h1>File upload</h1>
<%= typeof msg!= 'undefined' ? msg: ''%>
<form action="/upload" method="POST" enctype="multipart/form-data">
<div class="file-field input-field">
<div class="btn grey">
<span>File</span>
<input name="myImage" type="file">
</div>
<div class="file-path-wrapper">
<input class="file-path validate" type="text">
</div>
</div>
<button type="submit" class="btn">Submit</button>
</form>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/js/materialize.min.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
</body>
</html>
NODEJS CODE
const express = require('express');
const multer = require('multer');
const ejs = require('ejs');
const path= require('path');
const bodyParser = require('body-parser');
const app = express();
// middle ware
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
//set storage engine
const storage = multer.diskStorage({
destination: './public/uploads/',
filename:(res,file,cb)=>{
cb(null,file.fieldname+'-'+Date.now()+path.extname(file.originalname));
}
});
// init app
const upload = multer({storage:storage}).single('myImage');
const port = 3000;
// ejs
app.set('view engine','ejs');
//public folder
app.use(express.static('./public'));
// routing
app.get('/', (req,res)=>{
res.render('index');
});
app.post('/upload',(req,res)=>{
upload(res,res,(err)=>{
if(err){
res.render('index',{msg:err});
res.send('error uploading');
}else{
// console.log(req.file);
res.send('test');
}
});
});
app.listen(port,()=>{
console.log('server is connected at '+ port);
});
Error
TypeError: Cannot read property 'transfer-encoding' of undefined
at hasbody (/var/www/html/nodeuploads/node_modules/type-is/index.js:93:21)
at typeofrequest (/var/www/html/nodeuploads/node_modules/type-is/index.js:127:8)
at multerMiddleware (/var/www/html/nodeuploads/node_modules/multer/lib/make-middleware.js:18:10)
at app.post (/var/www/html/nodeuploads/app.js:40:4)
at Layer.handle [as handle_request] (/var/www/html/nodeuploads/node_modules/express/lib/router/layer.js:95:5)
at next (/var/www/html/nodeuploads/node_modules/express/lib/router/route.js:137:13)
at Route.dispatch (/var/www/html/nodeuploads/node_modules/express/lib/router/route.js:112:3)
at Layer.handle [as handle_request] (/var/www/html/nodeuploads/node_modules/express/lib/router/layer.js:95:5)
at /var/www/html/nodeuploads/node_modules/express/lib/router/index.js:281:22
at Function.process_params (/var/www/html/nodeuploads/node_modules/express/lib/router/index.js:335:12)
When i click submit button below message is displayed
transfer-encoding' of undefined
Please let me know if additional details are required for debugging this issue
Thanks

Cannot POST using express and body-parser

Please can you help me out, for some reason I am not able to post and am getting a "cannot POST /api/create" and when inspecting the page a 404 error is shown.
Here is my index.js:
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var mainRouter = require('./mainRouter.js');
var todoRoutes = require('./todoRoutes.js');
//tell express to use bodyParser for JSON and URL encoded form bodies
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
//mouting our routers
app.use('/', mainRouter);
app.use('/todo',todoRoutes);
app.listen(3000);
console.log("Express server running on port 3000");
And the corresponding todoRoutes.js file is where I require the post method:
var express = require('express');
var todoRoutes = express.Router();
var todoList = []; //to do list array
todoRoutes.get('/', function(req, res) {
res.sendFile(__dirname + '/views/todo/index.html');
});
todoRoutes.get('/create', function(req, res) {
res.sendFile(__dirname + '/views/todo/create.html');
});
todoRoutes.get('/api/list', function(req, res) {
res.json(todoList); //respond with JSON
});
todoRoutes.get('/api/get/:id',function(req, res){
res.json(todoList[req.params.id]);
});
todoRoutes.post('/api/create', function(req, res){
console.log("Creating the following todo:", req.body.todo);
todoList.push(req.body.todo);
res.send({redirect: '/api/list'});
});
and here is the corresponding html file:
<!DOCTYPE html>
<html lang = "en">
<head>
<title>Todo List: Create</title>
<meta charset="utf-8" />
</head>
<body>
<form action = "/api/create" method="post">
<div>
<label for="todo">Enter your new Todo:</label>
<input type="text" id="todo" name="todo">
</div>
<div class="button">
<button type="submit">Add</button>
</div>
</form>
</body>
</html>
If I put a console.log("") in the POST function of the todoRoutes.js file it will not be displayed, indicating that the function does not even get executed.
Any help will be very much appreciated.
You need to POST to /todo/api/create, based on your current route handling:
<form action = "/todo/api/create" method="post">

Why is the directory throwing 404 when rendering ejs

I am trying to make a page which just receives a get request from my index.js file and just displays "hello user". I have created a 'users.ejs' file in my express app which just renders a string from a 'users.js' file. There is a form in my index.ejs file which redirects to my users directory. The index file works well when I type the '/' directory in the url box but for some reason, the file throws a 404 not found error in the browser when I hit the submit on the form in the first page instead of showing the 'users.ejs' page, can anyone tell me why it does this?
index.ejs
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<h1><%= title %></h1>
<p>Welcome to <%= title %></p><br>
<form action='/users' method='get'>
Enter Name: <input type='text' name='thetext'></input><br><br>
<input type='submit' id='checkresponse'>enter</button>
</form>
<script type = 'text/javascript' src = '/dist/jquery.js'></script>
<script type = 'text/javascript' src = '/js/response.js'></script>
</body>
</html>
index.js
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Expr-Ass' });
});
module.exports = router;
users.js
var express = require('express');
var router = express.Router();
/* GET users listing. */
router.get('/users', function(req, res, next) {
res.render('users', {star:'Sparksiano'});
});
module.exports = router;
users.ejs
<!DOCTYPE html>
<html>
<head>
<title><%= star %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<h1>Welcome user!</h1>
</body>
</html>
Based off of comments below you may want to try something like this:
users.js
var express = require('express');
var router = express.Router();
/* Notice the path change */
router.get('/', function(req, res, next) {
res.render('users', {star:'Sparksiano'});
});
module.exports = router;
It sounds like you may be mounting your path to include a /users and then having a route that has a path of /users. Would be easier to troubleshoot if you posted the rest of the server side code.
I place the various ejs files in a folder and then point the express router to use that folder as a path:
var app = express();
app.set('port', 6000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
Then I route them to those pages:
app.get('/', function (req, res) {
res.render('index', {title: 'Express'});
});
app.get('/users', function (req, res) {
res.render('users', {star:'Sparksiano'});
});
Make sure the users.ejs page is in the same folder.

Resources