I have a simple html form:
<div class="signup-form">
<h2>Signup for an account</h2>
<form method="POST" action="/submit-signup">
<input type="text" title="username" placeholder="username" />
<input type="password" title="username" placeholder="password" />
<button type="submit" class="btn">Submit</button>
</form>
</div>
and an index.js with routes:
var bodyParser = require('body-parser')
const express = require('express')
const app = express()
const port = 3000
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
const Pool = require('pg').Pool
const pool = new Pool({
user: 'user',
host: 'localhost',
database: 'app',
password: 'password',
port: 5432,
})
app.get('/', function(req, res) {
res.sendFile(__dirname +'/index.html');
});
app.get('/login', function(req, res) {
res.sendFile(__dirname +'/login.html');
});
app.get('/signup', function(req, res) {
res.sendFile(__dirname +'/signup.html');
});
app.post('/submit-signup',(req, res) => {
console.log(req.body)
const username = req.body.username
const password = req.body.password
pool.query('INSERT INTO users (username, password) VALUES ($1, $2)', [username, password], (error, results) => {
if (error) {
throw error
}
response.status(201).send(`User added with ID: ${result.insertId}`)
})
})
app.listen(port, () => {
console.log(`App running on port ${port}.`)
})
Every time the form is submitted with answers the request body logs as {} and the error is thrown from the query because of the null value (the column in my database is set to not-null). I've tried most fixes from old stack overflow posts, so any help is appreciated
You are using the body-parser middleware. This middleware by default will try to parse every http body into a js-object based on a given json value.
As you are sending your data over an HTML form this data is not in JSON representation, but in the data generated by the HTML form.Mozilla Specs
To make this work you either need to iplement a way to read the body sent by the HTML form or use a more modern approach by sending a (REST) JSON request to your express server.
To make your code work use body-parser.urlencoded() as HTML form data is an url encoded text Ref to existing Stackoverflow answer
To make your form a bit more modern, use a JavaScript framework and follow a client-server pattern. Have a look at this tutorial REST tutorial with express
Your problem cuz you don't use a name tag in HTML form.
<div class="signup-form">
<h2>Signup for an account</h2>
<form method="POST" action="/submit-signup">
<input type="text" name="username" title="username" placeholder="username" />
<input type="password" name="password" title="password" placeholder="password" />
<button type="submit" class="btn">Submit</button>
</form>
</div>
Add name attribute in your html input field
Related
I have the following route in my express application:
router.get('/edit/:id', (req, res)=> {
let searchQuery = {_id : req.params.id};
console.log(searchQuery)
Address.findOne(searchQuery)
.then(address => {
res.render('myForm', {address:address});
})
.catch(err => {
console.log(err);
});
});
and my form is:
<form action="/edit/<%= address.id %>?_method=put" method="POST">
<input type="hidden" name="_method" value="PUT">
<br>
<input type="text" value="<%= address.name %>" name="name" class="form-control">
<br>
<input type="text" value="<%= address.email %>" name="email" class="form-control">
<br>
<button type="submit" class="btn btn-info btn-block mt-3">Update User</button>
</form>
It works correctly, I can see the data getting form the mongodb into myForm. Now after I update some data in this form and click the udpdate button i get : Cannot POST /edit/62185a7efd51425bbf43e21a
Noting that I have the following route:
router.put('/edit/:id', (req, res)=> {
let searchQuery = {_id : req.params.id};
console.log(`searchQuery = ${searchQuery}`)
Address.updateOne(searchQuery, {$set: {
name: _.extend(name, req.body),
email: req.body.email,
}})
.then(address => {
res.redirect('/');
})
.catch(err => {
res.redirect('/');
});
});
It looks like express call the get and not the put in my case. Any suggestion?
The browser itself will only do GET and PUT from a <form>. So, your browser is sending a POST and your server doesn't have a handler for that POST.
The ?_method=put that you added to your URL looks like you're hoping to use some sort of method conversion or override tool on the server so that it will recognize that form POST as if it were a PUT. You don't show any server-side code to recognize that override query parameter so apparently your server is just receiving the POST and doesn't have a handler and thus you get the error CANNOT POST /edit/62185a7efd51425bbf43e21a.
There are several different middleware solutions that can perform this override. Here's one from Express: http://expressjs.com/en/resources/middleware/method-override.html and you can see how to deploy/configure it in that document.
Basically, you would install the module with:
npm install method-override
and then add this to your server:
const methodOverride = require('method-override')
// override with POST having ?_method=PUT
app.use(methodOverride('_method'));
This will look at incoming POST requests with the ?_method=PUT query string and will modify the method per the parameter in the query string so that app.put() will then match it.
This is to be used when the client can only do GET or POST and can't do other useful methods such as PUT or DELETE.
As a demonstration, this simple app works and outputs got it! back to the browser and /edit/123456789?_method=put in the server console when I press the Update User button in the HTML form.
const app = require('express')();
const path = require('path');
const methodOverride = require('method-override');
app.use(methodOverride('_method'));
app.get("/", (req, res) => {
res.sendFile(path.join(__dirname, "temp.html"));
});
app.put('/edit/:id', (req, res) => {
console.log(req.url);
res.send("got it!");
});
app.listen(80);
And, temp.html is this:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<form action="/edit/123456789?_method=put" method="POST">
<br>
<input type="text" value="hello" name="name" class="form-control">
<br>
<input type="text" value="hello#gmail.com" name="email" class="form-control">
<br>
<button type="submit" class="btn btn-info btn-block mt-3">Update User</button>
</form>
</body>
</html>
You can create chainable route handlers for a route path by using app.route(). Because the path is specified at a single location, creating modular routes is helpful, as is reducing redundancy and typos.
Note: you must change the method in side form tag to PUT
<form action="/edit/<%= address.id %>" method="put">
//Backend.js
router.route('/edit/:id')
.get((req, res) => {
res.send('Get a random book')
})
.put((req, res) => {
res.send('Update the book')
})
I have the following route in my express application:
router.get('/edit/:id', (req, res)=> {
let searchQuery = {_id : req.params.id};
console.log(searchQuery)
Address.findOne(searchQuery)
.then(address => {
res.render('myForm', {address:address});
})
.catch(err => {
console.log(err);
});
});
and my form is:
<form action="/edit/<%= address.id %>?_method=put" method="POST">
<input type="hidden" name="_method" value="PUT">
<br>
<input type="text" value="<%= address.name %>" name="name" class="form-control">
<br>
<input type="text" value="<%= address.email %>" name="email" class="form-control">
<br>
<button type="submit" class="btn btn-info btn-block mt-3">Update User</button>
</form>
It works correctly, I can see the data getting form the mongodb into myForm. Now after I update some data in this form and click the udpdate button i get : Cannot POST /edit/62185a7efd51425bbf43e21a
Noting that I have the following route:
router.put('/edit/:id', (req, res)=> {
let searchQuery = {_id : req.params.id};
console.log(`searchQuery = ${searchQuery}`)
Address.updateOne(searchQuery, {$set: {
name: _.extend(name, req.body),
email: req.body.email,
}})
.then(address => {
res.redirect('/');
})
.catch(err => {
res.redirect('/');
});
});
It looks like express call the get and not the put in my case. Any suggestion?
The browser itself will only do GET and PUT from a <form>. So, your browser is sending a POST and your server doesn't have a handler for that POST.
The ?_method=put that you added to your URL looks like you're hoping to use some sort of method conversion or override tool on the server so that it will recognize that form POST as if it were a PUT. You don't show any server-side code to recognize that override query parameter so apparently your server is just receiving the POST and doesn't have a handler and thus you get the error CANNOT POST /edit/62185a7efd51425bbf43e21a.
There are several different middleware solutions that can perform this override. Here's one from Express: http://expressjs.com/en/resources/middleware/method-override.html and you can see how to deploy/configure it in that document.
Basically, you would install the module with:
npm install method-override
and then add this to your server:
const methodOverride = require('method-override')
// override with POST having ?_method=PUT
app.use(methodOverride('_method'));
This will look at incoming POST requests with the ?_method=PUT query string and will modify the method per the parameter in the query string so that app.put() will then match it.
This is to be used when the client can only do GET or POST and can't do other useful methods such as PUT or DELETE.
As a demonstration, this simple app works and outputs got it! back to the browser and /edit/123456789?_method=put in the server console when I press the Update User button in the HTML form.
const app = require('express')();
const path = require('path');
const methodOverride = require('method-override');
app.use(methodOverride('_method'));
app.get("/", (req, res) => {
res.sendFile(path.join(__dirname, "temp.html"));
});
app.put('/edit/:id', (req, res) => {
console.log(req.url);
res.send("got it!");
});
app.listen(80);
And, temp.html is this:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<form action="/edit/123456789?_method=put" method="POST">
<br>
<input type="text" value="hello" name="name" class="form-control">
<br>
<input type="text" value="hello#gmail.com" name="email" class="form-control">
<br>
<button type="submit" class="btn btn-info btn-block mt-3">Update User</button>
</form>
</body>
</html>
You can create chainable route handlers for a route path by using app.route(). Because the path is specified at a single location, creating modular routes is helpful, as is reducing redundancy and typos.
Note: you must change the method in side form tag to PUT
<form action="/edit/<%= address.id %>" method="put">
//Backend.js
router.route('/edit/:id')
.get((req, res) => {
res.send('Get a random book')
})
.put((req, res) => {
res.send('Update the book')
})
Evening All,
I'm trying to build a simple register page with mongodb, node, express, mongoose and angularJS.
I'm struggling to understand the relationship between all of the components and how to wire them all together.
This is my form...
<div class="main">
<p class="sign" align="center">Register</p>
<form class="form1">
<input class="un " type="email" align="center" placeholder="Email" name="username" required>
<input class="pass" type="password" align="center" placeholder="Password" name="password" required>
<button type="submit" class="btn btn-danger" align="center" ng-click="submit()">Register</button>
</div>
My controller for that view...
angular.module('registerCtrl', [])
.controller('registerController', function ($scope, $http, dataService) {
$scope.submit= function(){
console.log('clicked submit');
$http.post('/RegisterUser').then(function(response){
console.log(response.data);
console.log(response.status)
})
}
});
server.js for server and db logic...
const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const app = express();
const router = express.Router();
mongoose.connect("mongodb://localhost:27017/userDB", { useNewUrlParser: true });
const userSchema = new mongoose.Schema({
email: String,
password: String
});
const User = new mongoose.model("User", userSchema);
app.use(bodyParser.urlencoded({
extended: true
}))
app.use(express.static('node_modules'));
app.use(express.static('public'));
const port = 3000;
app.listen(port);
console.log('Server is running on port 3000');
//POSTS
app.post("/RegisterUser", function (req, res) {
const newUser = new User({
email: req.body.username,
password: req.body.password
});
newUser.save();
})
view routes...
angular.module('app.routes', [])
.config(function ($routeProvider) {
$routeProvider
.when("/", {
templateUrl: "views/Login.html"
})
.when("/Register", {
templateUrl: "views/Register.html",
controller: "registerController"
})
.when("/Home", {
templateUrl: "views/Home.html",
controller: "homeController"
})
.when("/CocktailDetails", {
templateUrl: "views/CocktailDetails.html",
controller: "cocktailDetailsController"
})
.when("/Favourites", {
templateUrl: "views/Favourites.html",
controller: "favouritesController"
})
.otherwise({
redirectTo: "/"
})
})
Essentially what I want to achieve is simply posting the inputted email and password to the database and then, if the POST was successful divert the view route to my home view.
Should I be passing in the data from the form into the post request in my controller as opposed to the server side? As currently the post data is being passed as null.
Is someone able to explain the best way to achieve this and describe the relationship between the database, server and client side framework in this scenario.
Thanks
Client
It looks like your form is missing ng-models and you're also not posting their data. Add ng-model to the inputs:
<input type="email" ng-model="form.username">
<input type="password" ng-model="form.password">
Also create their bindings in the controller. Then pass the form data along to the server when you post:
.controller('registerController', function ($scope, $http, $location, dataService) {
// injecting $location now ^
$scope.form = { // <-- An object whose properties are bound to the form inputs
username: '',
password: ''
}
$scope.submit = function(){
console.log('clicked submit');
$http.post('/RegisterUser', $scope.form) // <-- posting `$scope.form` data now
.then(function(response){
console.log(response.data);
console.log(response.status);
$location.path('/Home'); // <-- redirecting to Home route
})
}
});
Server
Since there was no data being posted before, req.body was empty on the server. The server is also not sending back a response. If you wanted to send back the user object, you could add this to the server route after newUser.save():
return res.status(200).send(newUser);
send is what sends a response, return just exits the function.
Making a signup page for an app I'm going to build later. Just created a simple as can be node server, and it's running on port 3000. I created a React app with a simple form interface, running on port 3001. The user fills in the form and hits the register button, and this should send an email and password to the post route of /register.
But I get "incorrect form submission" every time. It looks like just a json object in the network pane "{email: dummy#email, password: 123}", so I'm not sure what this means...
onSubmitRegister = () => {
fetch('http://localhost:3000/register', {
method: 'post',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: this.state.email,
password: this.state.password
})
})
.then(response => response.json())
.then(data => console.log(data));
}
The node server looks like this:
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
app.use(express.static("public"));
app.use(bodyParser.urlencoded({extended: true}));
app.get("/", (req, res) => {
res.send("Hello");
})
app.post("/register", (req, res) => {
console.log(req.body);
})
app.listen(3000, () => {
console.log("Server started on port 3000");
});
For now, I just want it to console log the req.body, so I know everything is working OK before I go on to build a MongoDB database and start adding documents to collections. Stack Overflow and other forum threads I've googled suggest checking the headers are correct. This looks OK to me. Am I missing something?
EDIT: This is what the form looks like, the entire render function:
render(){
return(
<div>
<div className="text-center">
<form className="form-signin">
<h1 className="h3 mb-3 font-weight-normal">Ohaii Sign Up</h1>
<label for="inputEmail" className="sr-only">Email address</label>
<input
type="email"
id="inputEmail"
className="form-control"
placeholder="Email address"
required=""
autofocus=""
onChange={this.onEmailChange}
/>
<label for="inputPassword" className="sr-only">Password</label>
<input
type="password"
id="inputPassword"
className="form-control"
placeholder="Password"
required=""/>
<label for="inputPassword" className="sr-only">Password</label>
<input
type="password"
id="confirmPassword"
className="form-control"
placeholder="Confirm Password"
required=""
onChange={this.onPasswordChange}
/>
<div className="btn btn-block btn-social btn-google" style={{'color': '#fff'}}>
<span className="fa fa-google"></span> Sign Up with Google
</div>
<div className="btn btn-block btn-social btn-facebook" style={{'color': '#fff'}}>
<span className="fa fa-facebook"></span> Sign Up with Facebook
</div>
</form>
</div>
<button
onClick={this.onSubmitRegister}
className="btn btn-lg btn-primary btn-block"
>Register</button>
</div>
)
}
As you are sending JSON data (both your body is JSON and you are setting the JSON content type), I would recommend to change the bodyParser middleware to:
app.use(bodyParser.json());
At least, in my quick test I was then able to send data from the browser and saw it on the server. With bodyParser.urlencoded that was not the case, however, I did not get the same error as you did.
In addition, you should return some response from the server, for example, I used:
app.post("/register", (req, res) => {
console.log(req.body);
res.end("{}");
});
Was a problem specific to my environment. Just cleared the npm cache and that fixed it.
I've been searching around but couldn't seem to find an answer to this...
I'm really new to NodeJS. I'm trying to write a server that will take the POST request when user try to login, then redirect to the home page using GET, and the home page will now display the username.
so if the url is home.html, on the page it says guest, if the url is home.html?username=adam then on the page it says adam
On my login.html, there's a form similar to this
<FORM ACTION="login.html" METHOD="POST">
<CENTER>
Username: <INPUT TYPE="text" ID="username" required=true><BR>
Password: <INPUT TYPE="password" ID="password" required=true><BR>
<INPUT TYPE="SUBMIT">
</CENTER>
</FORM>
On my server.js, I have the block trying to get the username and redirect
http.createServer(function (req, res) {
if(req.url == "login.html" && req.method == "POST")
{
req.on('data', function(chunk) {
var someData += chunk;
var username = //get from POST data
//attempt to redirect
res.writeHead(200, {"Location":"home,html?username=adam"});
res.end();
});
}
}
I was able to get the username and log it, but when I tried to redirect, the page came back blank, and the url still says login.html...
I'm not even sure if I'm doing it correctly, please help.
As you are new to nodejs please try to use REST API for communication instead of redirecting to other pages directly.
To retrieve the form data in server js you need to install body parser which is detailed here:
[https://github.com/expressjs/body-parser][1]
Then update your server js like below:
var app = require('express')();
var http = require('http').Server(app);
var bodyParser = require('body-parser')
app.use(bodyParser());
app.get('/login', function (req, res) {
res.sendfile('login.html');
});
app.get('/home', function (req, res) {
res.sendfile('home.html');
});
app.post('/login', function (req, res) {
console.log("Username:",req.body.username);
console.log("password:",req.body.password);//just for reference do not show anywhere
res.redirect('/home?username='+req.body.username);
});
http.listen(3000, function () {
console.log('listening on *:3000');
});
And your login login.html will looks like this:
<FORM ACTION="/login" METHOD="POST">
<CENTER>
Username: <INPUT TYPE="text" name="username" ID="username" required=true><BR>
Password: <INPUT TYPE="password" name="password" ID="password" required=true><BR>
<INPUT TYPE="SUBMIT">
</CENTER>
</FORM>
Do necessary action on home page as now you are avail with username on url..hope this help..let me know if any doubts. Happy coding:)