I am building a search engine app with Express that queries the Twitter API v1.1. Currently, I am trying to submit the search string to my server by parsing form data with the bodyParser module. Here is the code:
index.ejs
...
<form method="GET" action="/results">
<input id="input" type="text" name="search">
<button id="searchButton">+</button>
</form>
...
server.js
var express = require('express'),
bodyParser = require('body-parser');
var app = express();
var port = process.env.PORT || 8080;
app.set('view engine', 'ejs');
app.use(express.static(__dirname + "/public");
var urlencodedParser = bodyParser.urlencoded({ extended: false })
app.get('/', function(req, res) {
res.render('index');
});
app.get('/results', urlencodedParser, function (req, res) {
console.log(req.body);
res.render('results')
});
app.listen(port, function() {
console.log('Our app is running on http://localhost:' + port);
});
The code shown will return { } to the console. If I try and access req.body.search it returns undefined (obviously). What is the issue here? Why is it not logging my search string?
You're using the wrong body decoder. If you're submitting a form (application/x-www-form-urlencoded is the default enctype for forms), you will need bodyParser.urlencoded() instead of bodyParser.text(). The latter is for plaintext request data, not form data.
Additionally, you should also be using method="POST" and a POST route (app.post('/results', ...)) instead of method="GET" and a GET route. Since GET requests almost never have a body, the browser instead transforms the form data into a querystring that is then appended to the url itself. This means your form data is currently in req.query instead of req.body. Switching to POST though will cause the browser to send the form data in the request body, and the form data will be in req.body as expected.
Related
I have a code where I get data using the post method, but such an error occurs, what's the problem?
todos.js
router.post('/create', async (req, res) => {
const todo = new Todo({
title: req.body.title
})
todo.save();
create.hbs
<form action="/create" method="POST">
<h2>Create todo</h2>
<div class="input-field">
<input type="text" name="title">
<label>Todo title</label>
</div>
<button type="submit" class="btn">Create</button>
</form>
index.js
const express = require('express');
const mongoose = require('mongoose');
const expressHandlebars = require('express-handlebars');
const PORT = process.env.PORT || 3000;
const todoRoutes = require('./routes/todos')
app.use(todoRoutes);
app.use(express.urlencoded({
extended:true
}));
It appears that req.body is undefined. That would mean that you don't have any middleware that is reading and parsing the body of the POST request and placing the results into req.body.
Since this is a regular form post, it will using the content-type application/x-www-form-urlencoded which can be parsed with the middleware express.urlencoded().
I see you have that middleware, but it is AFTER your route so it won't run before your route gets called. Route handlers and middleware run in the order they are declared. So, change this:
app.use(todoRoutes);
app.use(express.urlencoded({
extended:true
}));
to this:
app.use(express.urlencoded({
extended:true
}));
app.use(todoRoutes);
Also, keep in mind that you should be doing server-side validation of everything that the client sends. In this case, you might be getting a request that doesn't have a title or has an empty title. Your server should be checking for that and return a non 200 http status if you are getting bad data from the client. Do not just assume that all the correct data has arrived with the incoming request. Verify the data before using it. This is the brute force dirty work that gives you a reliable server.
My guess is that you have your app.use() in the incorrect order. Expressjs executes these in order.
Update your index.js to
const express = require('express');
const mongoose = require('mongoose');
const expressHandlebars = require('express-handlebars');
const PORT = process.env.PORT || 3000;
const todoRoutes = require('./routes/todos')
const app = express()
app.use(express.urlencoded({
extended:true
}));
app.use(todoRoutes);
I am working on layouts and templating. I have a site where I have files "views/partials/header.ejs" and "views/partial/footer.ejs". I have the app.js file with templating set up as follows:
const express = require('express')
const bodyParser = require('body-parser');
const nodemailer = require('nodemailer');
const ejs = require('ejs');
const date = require(__dirname + '/date.js');
const app = express();
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({extended: true}));
app.use(express.static("public"));
app.get('/', function(req, res) {
const year = date.getYear();
res.render('home', {copyrightYear: year})
});
app.listen(3000, function() {
console.log('Server started on port 3000');
});
What I need to do is pass the const copyrightYear into the partial "footer" instead of having to to input into each route. Any advice would be welcomed.
Thanks in advance.
you can't do that because when you make a request the server get the required file the does the logic on it and then it send it back to the browser .
so when you use this
app.get('/', function(req, res) {
const year = date.getYear();
res.render('home', {copyrightYear: year})
});
the server will get the home file which includes the partials files then pass the data then send it to the browser .
so you must make separate request for each file you want and then do the logic on it
I'm trying to do the most basic POST request in express but my req.body keeps returning undefined, I've googled similar issues but I can't find the solution that would work for me.
The form in HTML:
<form method="POST" class="vote">
<input type="text" name="test">
<button type="submit">TEST VOTE</button>
</form>
and in my post.js file
const express = require('express');
const app = express();
app.use(express.urlencoded({
extended: true
}));
app.post('/test', function (req, res) {
console.log('post to /test');
var data = req.body.test;
console.log(data);
What am I doing wrong here?
Try using body-parser node module which will parse the post data and append it on request object so that you can access it.
body-parser extract the entire body portion of an incoming request stream and exposes it on request.body.
const express = require('express');
const bodyParser = require("body-parser");
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.post('/test', function (req, res) {
console.log('post to /test');
var data = req.body;
console.log(data);
//rest of the code
}
Actually you didn't set the "action" field in your "form" tag.
You have to set your action field to
action= "/test"
this is my first time when I'm setting up the server and need help. So my goal is to set up server by NodeJS and Expresss. Let's say we have an app with Admin and Users. When Admin clicks a button, it sends some data for the server, then Users can fetch the data.
So this is my server set up:
const express = require('express')
const app = express()
const port = 3000
app.get('/', (req, res) => res.send('Hello World!'))
app.listen(port)
I can add some post method, let's say:
app.post('/', (req, res) => ....);
So I can prepare server reaction for listening the POST method, but I have no idea how to send some data from my app by clicking an button (I mean calling this post method). I've watched a bunch of tutorials and haven't seen any real-world exercises.
To receive the POST parameters, you need the body-parser module, which you can include in your app.js like this,
var bodyParser = require('body-parser');
app.use(bodyParser.json());
And here is how you can receive your form fields which are being sent through the POST method,
app.post('/', function(req, res) {
var someField1 = req.body.some_form_field;
var someField1 = req.body.form_field1;
});
Hope this helps!
On your express server
var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.post("/", (req,res) => {
res.send("Hello");
});
On your webpage/app, You can use axios.
Lets say your express server running with localhost and port 4000.
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
var instance = axios.create({
baseURL: "http://localhost:4000" //use your express server's url(address) and port here
});
function onclick(){
instance.post("/").then( response => {
//response.data will have received data
}
}
</script>
You can use this function and call it on your button click
You can simply use jquery in your HTML page like this to call your api:
$("button").click(function(){
$.post("/", function(data, status){
alert("Data: " + data + "\nStatus: " + status);
});
});
And Send data from your api:
var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.post('/', function(req, res) {
var obj = {};
obj.name="hello";
obj.lname="world"
res.json(obj);
});
Example:
HTML:
Your form elements should have name (it is mandatory) to access these in post body request.
<form method="post" action="/">
<input type="text" name="Name" />
<br>
<input type="text" name="Telephone" />
<br>
<input type="submit" />
</form>
app.js
const express = require('express')
const app = express()
const port = 3000
var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.post('/', (req, res) => {
name = req.body.Name;
telephone = req.body.Telephone;
res.render('somefolder/index', {
name: name,
telephone: telephone,
});
// Above code is for reference if you want to load another page after post complete and get posted values in this page too.
res.end();
});
I'm doing a post request to '/' with a simple text input and expecting to see the data entered in req.body.course. When console logging req.body.course, I am getting an empty object back.
HTML
<html>
<head><title>New Course</title></head>
<body>
<form id="myform" action="/" method="post">
<input type="text" name="course" id="mytext" />
<input type="submit" id="mysubmit" />
</form>
</body>
</html>
SERVER
var express = require('express');
var bodyParser = require('body-parser');
var app = express()
app.use(bodyParser.json())
app.set('views', __dirname + '/views');
app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');
app.post('/', function (req, res) {
var course = req.body.course;
res.send(course);
});
app.get('/', function (req, res) {
res.render('index');
});
app.listen(4000, function() {
console.log("Server is listening on port", 4000);
});
OUTPUT OF REQ.BODY
{}
Try
app.use(bodyParser.urlencoded())
you have to tell in headers what is the MIME type of your request
just add in request.
Content-Type='application/json'
Try to add the urlencoded middleware.
app.use(bodyParser.urlencoded())
or
app.use(bodyParser.urlencoded({
extended: true
}))
This parses URL encoded bodies since your request format is urlencoded.
You can refer to bodyparser urlencoded documentation.