unable to capture response to a POST request to a node server - javascript

I am learning to use node and express. I am creating a demo site using node express and google translate API to learn the various functionalities. The issue I'm running into is that when I post data to the server to be computed and returned, the server receives the request and sends the response, but the browser does not display the result. Instead the console diplays "navigated to localhost:8080/?'. I am hosting locally.
Here's the code for the server app:
var express = require('express');
var http = require('http');
var bodyParser = require('body-parser');
var path = require('path');
var fs = require('fs');
var morgan = require('morgan');
var settings = require('./settings');
var googleTranslate = require('google-translate')(settings.googleApiKey);
var port = 8080;
var hostname = 'localhost';
var app = express();
app.use(morgan('dev'));
app.use(bodyParser.json());
app.use(express.static(__dirname));
app.post('/', (req, res, next) => {
console.log("incoming post request");
console.log("text to detect: " + req.body.text);
googleTranslate.detectLanguage(req.body.text, function(err, detection) {
console.log(detection.language);
res.status(200);
res.contentType('text/plain');
res.end(detection.language);
});
});
var server = http.createServer(app);
server.listen(port, hostname, function() {
console.log('Server running at http://' + hostname + ':' + port);
});
The code for the function that is supposed to make the Ajax call and display the response. This is in a file that is called from a script tag in the index.html (get-langdetect.js):
var inputField = document.querySelector('#input');
var detectOutput = document.querySelector('#langlayer-output');
var getLang = function getLang() {
const data = JSON.stringify({
text: inputField.value
});
fetch('http://localhost:8080/', {
method: "POST",
headers: {
'Content-type': 'application/json',
},
body: data
}).then((response) => {
if (response.ok) {
console.log('received response!');
return response.body;
}
}).then((data) => {
console.log(data);
inputField.innerHTML = '<text>' + data + '</text>';
});
};
Pertinent index.html code snippet:
<div class="jumbotron">
<div class="center-elem">
<h1 class="center-elem">Detection</h1>
</div>
<form>
<div class="input-group">
<input type="text" class="form-control" placeholder="Enter text to detect" id="input">
<div class="input-group-btn">
<button class="btn btn-default" type="submit" onclick="getLang()">
Submit
</button>
</div>
</div>
<div id="langlayer-output">
</div>
</form>
</div>
<script src='./get-langdetect.js'></script>

When forms are submitted, it is expected that they either refresh the page, or navigate to the url in the action attribute on the <form>.
A quick way to avoid this is to put return false; after your function.
<button class="btn btn-default" type="submit" onclick="getLang(); return false;">
Submit
</button>
Here's a good read on the subject.
http://www.codexpedia.com/javascript/submitting-html-form-without-reload-the-page/
I'd recommend doing some homework on <form> elements and their basic usage to understand the typical behavior.

Related

cannot access the POST form data sent by HTML/Javascript code at node js code

I made a simple nodejs server which serves a html page to the user.The page contains a input text box of userID. When the user presses the button submit, I take that userID entered by the user and put it in form Data and send it to my server function (submitForTest) through POST method.
Now, inside my function of nodejs which handles submitForTest, I tried to access the userID , but I was getting res.body as {} , so not able to figure out how to access userID here.
Can anyone please point what I need to get the userID at my node js code.
My HTML file :
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div>
<label>User ID</label>
<div>
<input type="text" id="userid" >
</div>
</div>
<div>
<div>
<button type="submit" onclick="submitForTest()">Submit</button>
</div>
</div>
<script type="text/javascript">
function submitForTest()
{
var userID = document.getElementById('userid').value;
let formData = new FormData();
formData.append("userID", userID);
//alert("hello");
fetch('http://MY-SERVER:3000/submitForTest', {method: "POST", body: formData});
}
</script>
</body>
</html>
My Node js file :
'use strict'
const fs = require("fs")
const express = require('express')
var path = require('path')
const app = express()
var bodyParser = require('body-parser')
app.use( bodyParser.json() ); // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true
}));
var jsonParser = bodyParser.json();
app.get('/',function(req,res) {
res.sendFile('small.html');
});
app.post('/submitForTest', function(req, res) {
//want to print userID here .. but the below is coming as {} here ..
console.log(req.body);
})
// Tell our app to listen on port 3000
app.listen(3000, function (err) {
if (err) {
throw err;
}
console.log('Server started on port 3000')
})
Please help.
Regards
The problem is FormData is sending body encoded as multipart/form-data. You'll have to add middleware able to handle multipart body format. Busboy or multer for example.
Example of using multer to upload a file and send userID field:
// --- form
<form action="/submitForTest" enctype="multipart/form-data" method="post">
<input type="file" name="uploaded_file">
<input type="text" name="userID">
<input type="submit" value="Submit">
</form>
// --- server
var multer = require('multer')
var upload = multer({ dest: './uploads/' }) // where the uploaded files will be stored
app.post('/submitForTest', upload.single('uploaded_file'), function (req, res) {
// req.file is the name of your file in the form above, here 'uploaded_file'
// req.body will hold the text fields, if there were any
console.log(req.file, req.body)
});
Or to send your data in urlencoded or json format. Something like that for json for example:
function submitForTest()
{
var userID = document.getElementById('userid').value;
fetch('http://MY-SERVER:3000/submitForTest', {
method: "POST",
headers: {
'Content-type': 'application/json',
},
body: JSON.stringify({ userID }),
});
}

How to Fix : TypeError: enrollUser is not a function at HTMLButtonElement.onclick

I am trying to call enrollUser function on onclick event in index.html. enrollUser() is also defined in index.js. Still it giving me an error on onclick event.
Heres are codes for your reference. Let me what's wrong in these..
enrollUser.js
'use strict';
const FabricCAServices = require('fabric-ca-client');
const { Wallets } = require('fabric-network');
const fs = require('fs');
const yaml = require('js-yaml');
const path = require('path');
async function main(uname) {
try {
// load the network configuration
let connectionProfile = yaml.safeLoad(fs.readFileSync('../gateway/connection-uni.yaml', 'utf8'));
// Create a new CA client for interacting with the CA.
const caInfo = connectionProfile.certificateAuthorities['ca.uni.example.com'];
const caTLSCACerts = caInfo.tlsCACerts.pem;
const ca = new FabricCAServices(caInfo.url, { trustedRoots: caTLSCACerts, verify: false }, caInfo.caName);
console.log(`----------------- Creating ID for: ${uname} -----------------`)
//function body
}
module.exports.execute = main;
index.js
const express = require('express');
const app = express();
const cors = require('cors');
const port = 3000;
const enrollUser = require('./enrollUser');
app.use(cors());
app.use(express.json()); // for parsing application/json
app.use(express.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded
app.set('title', 'Educhain App');
app.get('/', function (req, res) {
res.sendFile( __dirname + "/" + "index.html" );
});
app.post('/enrollUser', (req, res) => {
enrollUser.execute(req.body.uname)
.then(() => {
console.log('User credentials added to wallet');
const result = {
status: 'success',
message: 'User credentials added to wallet',
uname: req.body.uname
};
res.json(result);
})
.catch((e) => {
const result = {
status: 'error',
message: 'Failed',
error: e
};
res.status(500).send(result);
});
});
app.listen(port, () => console.log(`Distributed Certification App listening on port ${port}!`));
index.html
<script type="text/javascript" src="./app.js"></script>
<input type="text" placeholder="Enter Username" name="uname" id="uname" required>
<button type="submit" id="enrollUser" onclick="enrollUser()">Login</button></div>
app.js
let enrollUser = () => {
const uname = document.getElementById('uname').value;
$.post('http://localhost:3000/enrollUser', {uname: uname})
.done((result) => {
console.log(result);
if (result.status === 'success') {
$(".studentTable tbody").append(
"<tr>" +
"<td>1</td>" +
"<td id='uname'>" + result.uname + "</td>" +
"</tr>"
);
} else {
$(".error-toast").toast('show');
}
})
.fail((xhr, status, error) => {
$(".error-toast").toast('show');
});
};
Also giving error to app.js in index.html--> GET http://localhost:3000/app.js net::ERR_ABORTED -- > 404 (Not Found)
Not getting any error on console, but it's on chrome developer tool. Please let me know what's missing.
I am using the same structure as this project https://github.com/avi-githb/Certification_Network_Hyperledger_fabric/tree/master/application
To make this work the way you explained in the comments you would need to run the server first. For you, this is the app.js file.
Make sure to have node installed and run this command in your project directory.
node index.js
You will know the server running by seeing a message with the port in the console.
Secondly, modify your HTML to contain a form, then pass the form on submitting to the endpoint enrollUser
<form action="http://localhost:3000/enrollUser" method="POST">
<input type="text" placeholder="Enter Username" name="uname" id="uname" required>
<button type="submit">Login</button>
</form>
This should work well for you, learn more about forms here.

Twilio JavaScript - SMS from client to server

I've found docs teaching on how to implement Twilio on server-side using Node, however, I couldn't find an end-end example where I can send a SMS coming from my client app.
Can anyone tell me what the implementation would look like to send a post custom SMS from client to server?
Disclaimer my server file is named as app.js and my client file is named as index.js
**1- This is what I have currently setup on my app.js
const express = require('express');
const app = express();
const path = require('path');
const twilio = require('twilio');
const bodyParser = require('body-parser');
//JSON DATA
const guests= require('./public/data/Guests');
app.use(bodyParser.urlencoded({extended: false}));
app.use(express.static('public'));
//SET PORT
app.set("port", process.env.PORT || 3000);
//GET JSON DATA
app.get('/data', function(req, res) {
Promise.all([guests])//combine requests into one object
.then(([guests]) => {
res.send({guests});
});
});
//CATCHALL
app.get("/*", function(req,res){
let file = req.params[0] || "/views/index.html";
res.sendFile(path.join(__dirname, "/public/", file));
});
//LISTEN ON PORT
app.listen(app.get("port"), function(){
console.log("Listening on port: " , app.get("port"));
});
let client = new twilio('xxxxxxxxxx', 'xxxxxxxxxxxxx');
app.post('/sms', (request, result) => {
const message = request.body.message;
client.messages.create({
to: +1847820802492359,
from: +8475302725792530 ,
body: message
}).then(() => {
// message sent successfully, redirect to the home page.
res.redirect('/');
}).catch((err) => {
console.error(err);
res.sendStatus(400);
});
});
-2 am trying to process a dynamic message in my index.js. The code works on the DOM properly, it is just the SMS with Twilio that isn't posting the message to the server
$(function() {
$.ajax({
type: "GET",
url: "/data",
success: res => {
//console.log(res);
handleMessage(res);
},
error: err => console.log(err)
});
//message method
let handleMessage = (res) => {
const getFirstName = res.guests.map(name => name.firstName);
//populate drop-down select
let handleSelect = () => {
//adds first names to select dropDown
$.each(getFirstName, function(i, value) {
$('#selectName').append($('<option>').text(value).attr('value', value));
});
};
handleSelect();
let handleSubmit = () => {
$("#form").submit(function(e) {
e.preventDefault();
let name = $('#selectName').val();
let greetGuest = `Welcome ${name}!`;
console.log(greetGuest);
//append to Dom
$('.showMessage').append(`<div class="newMessage"><span>${greetGuest}</span></div>`);
});
};
handleSubmit()
};
});
-3 HTML form
<form id="form" action="/sms" method="POST">
<label>
<label for=selectName>Guest
<select id="selectName" class="select " name="sms">
</select>
</label>
</label>
<input type="submit" value="send" class="btn btn-success" />
</form>
Am I having an asynchronicity issue here?
Twilio developer evangelist here.
I can give you a basic example here, which should give you a good idea of how to achieve this. I'll start with the server side, which you already have the basics of.
Firstly, I would recommend you use a POST request rather than a GET, simply because GETs can be easily repeated by users or cached by proxies. I assume you are using Express as the web application server. You will also need the body-parser module to read the data that we send from the client side.
const Twilio = require('twilio');
const express = require('express');
const bodyParser = require('body-parser');
const app = new express();
app.use(bodyParser.urlencoded({extended: false}));
app.use(express.static('public'));
const twilio = new Twilio(YOUR_ACCOUNT_SID, YOUR_AUTH_TOKEN);
app.post('/messages', (request, result) => {
const message = request.body.message;
twilio.messages.create({
to: TO_NUMBER,
from: FROM_NUMBER,
body: message
}).then(() => {
// message sent successfully, redirect to the home page.
res.redirect('/');
}).catch((err) => {
console.error(err);
res.sendStatus(400);
});
});
app.listen(3000);
This sets up a server which is serving static files from a public directory and then has one endpoint, POST to /messages, that sends a message.
We now need to create the client side. I shall do this in HTML only for simplicity. You need a form that will POST to the /messages endpoint with, in this case, a single field for the message. I've included a textarea to write the message in and a button to submit the form. If you save this as index.html in the public directory where you run the application from then it should work.
<!DOCTYPE html>
<html lang="en">
<head>
<title>Send a message!</title>
</head>
<body>
<h1>Send a message!</h1>
<form action="/messages" method="POST">
<label for="message">What would you like to send?</label>
<textarea name="message" id="message"></textarea>
<button type="submit">Send!</button>
</form>
</body>
</html>
Let me know if that helps at all.
Update
So you're looking to make the request to the server using Ajax so your page doesn't reload and you can display a different message. Your current form seems to have removed the message textarea that I added, I'll put it back in again. I assume you also want to send the message to whichever guest you are welcoming at the time, but I don't know how that works in your system, so I'm going to avoid that for now and hopefully you can sort it out.
So, if you update your form to something like this:
<form id="form" action="/sms" method="POST">
<label>
<label for=selectName>Guest
<select id="selectName" class="select " name="sms">
</select>
</label>
</label>
<label for="message">Message</label>
<textarea id="message" name="message"></textarea>
<input type="submit" value="send" class="btn btn-success" />
</form>
Then you need to add to your JavaScript a way to actually submit the form (since you are preventing the submission with e.preventDefault().
const $form = $('#form');
$form.submit(function(e) {
e.preventDefault();
let name = $('#selectName').val();
let greetGuest = `Welcome ${name}!`;
console.log(greetGuest);
$.ajax({
url: $form.attr('action'),
type: $form.attr('method'),
data: $form.serialize(),
success: function(data) {
console.log("The message has been sent");
},
error: function() {
console.error("The message couldn't be sent");
console.error(...arguments);
}
})
//append to Dom
$('.showMessage').append(
`<div class="newMessage"><span>${greetGuest}</span></div>`
);
});
In this case we are hooking into the callback for the submit event to make a new $.ajax request to the form's action, using the method (POST), and including the form data (which we get from $form.serialize()). We then setup success and error callbacks as you've done at the top of the function.
Let me know if this helps.

Sending data from HTML form to server

I am trying to send form data via ajax to a nodejs server.
Here's what my code looks like (EDITED):
<div id="inputid" style="width: 400px; height:400px">
<p> Please enter the respective values in each field and hit Submit </p>
<form id="sendCoordinates" action="http://localhost:8080/geodata" method="post">
MinLat: <input type="text" name="MinLat" id="minlat"><br>
MaxLat: <input type="text" name="MaxLat" id="maxlat"><br>
MinLong: <input type="text" name="MinLong" id="minlong"><br>
MinLong: <input type="text" name="MaxLong" id="maxlong"><br>
<input type="submit" value="submit" id="s1">
</form>
<script>
$(document).ready(function() {
$(sendCoordinates)
.on('success.form.fv', function(e) {
// Prevent form submission
e.preventDefault();
var $form = $(e.target),
formData = new FormData(),
params = $form.serializeArray();
$.each(params, function(i, val) {
formData.append(val.name, val.value);
});
console.log(formData);
$.ajax({
url: $form.attr('action'),
data: formData,
cache: false,
contentType: false,
processData: false,
type: 'POST',
success: function(result) {
console.log(result);
}
});
});
});
</script>
My server side code looks like this :
var express = require("express");
var path = require("path");
var bodyParser = require("body-parser");
var app = express();
app.use(express.static(__dirname + "/public"));
app.use(bodyParser.json());
// Initialize the app.
var server = app.listen(process.env.PORT || 8080, function () {
var port = server.address().port;
console.log("App now running on port", port);
});
// for debugging purposes, just logging the request to check
// if request received
app.post("/geodata", function(req, res) {
console.log(req.body);
});
I am trying this out but I am unable to send the form successfully, and upon hitting submit, nothing happens. I am not able to log the formData on the client side, neither am I able to log the output at the endpoint on the server side.
Can someone point out what I might be doing wrong? All I get is an empty {} when I hit submit. Is my "action" tag in my form pointing to the correct url for posting to the endpoint /geodata?

Sending Email with Node Mailer and Sendgrid in Angular MEAN stack using angular-fullstack from Yeoman

I am trying to understand where to locate the logic to send an email via a contact form in my Angular App (using angular-fullstack MEAN stack from Yeoman).
I can add the logic to send an email in the app.js file on the server side using nodemailer and sendgrid and everything works and an email is sent every time I refresh the server, however I am a little fuzzy on where to place the logic so that it only gets sent once the form is submitted and it hits the server side.
This is what the create action looks like on the Express JS side...
exports.create = function(req, res) {
Contact.create(req.body, function(err, contact) {
if(err) { return handleError(res, err); }
return res.json(201, contact);
});
};
Here is the code in app.js that is working, but obviously not in the right place...
var nodemailer = require('nodemailer');
var sgTransport = require('nodemailer-sendgrid-transport');
var options = {
auth: {
api_user: 'username', // 'SENDGRID_USERNAME' - Recommended to store as evn variables
api_key: 'password', // 'SENDGRID_PASSWORD'
}
};
var mailer = nodemailer.createTransport(sgTransport(options));
var email = {
to: 'sendto#email.com',
from: 'sendfrom#email.com',
subject: 'Test Email',
text: 'Awesome Email',
html: '<b>Bold and Awesome Email</b>'
};
mailer.sendMail(email, function(err, res) {
if (err) {
console.log(err)
}
console.log(res);
});
Coming from a rails background my initial thought is to stick the logic in the create action so that if the object is created successfully the email gets sent. Is this a correct way of thinking about it in this scenario...I am new to the MEAN stack.
Thanks for any help...
You need to create a route on the server that you can post form values to from Angular using $http.post.
The following lets you enter details in an Angular form. The form is then posted to Node where the req.body values are extracted and added email object. The email is then send by SendGrid.
SERVER.JS
var express = require('express');
var http = require('http');
var bodyParser = require('body-parser');
var dotenv = require('dotenv');
dotenv.load(); //load environment variables from .env into ENV (process.env).
var sendgrid_username = process.env.SENDGRID_USERNAME;
var sendgrid_password = process.env.SENDGRID_PASSWORD;
var sendgrid = require('sendgrid')(sendgrid_username, sendgrid_password);
var email = new sendgrid.Email();
var app = express();
app.use(bodyParser.json()); //needed for req.body
app.set('port', process.env.PORT || 3000);
app.use(express.static(__dirname + '/public'));
app.post('/email', function(req, res) {
email.addTo(req.body.to);
email.setFrom(req.body.from);
email.setSubject(req.body.subject);
email.setText(req.body.text);
email.addHeader('X-Sent-Using', 'SendGrid-API');
email.addHeader('X-Transport', 'web');
sendgrid.send(email, function(err, json) {
if (err) {
return res.send("Problem Sending Email!!!!");
}
console.log(json);
res.send("Email Sent OK!!!!");
});
});
var server = http.createServer(app);
server.listen(app.get('port'), function() {
console.log('Express server listening on port ' + app.get('port') ) ;
});
INDEX.HTML
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="utf-8">
<title></title>
<!-- CSS -->
</head>
<body ng-controller="MainCtrl">
<form name="emailForm">
<div class="group">
<input type="email" name="to" ng-model="email.to" ng-required="true">
<label>To</label>
</div>
<div>
<input type="email" name="from" ng-model="email.from" ng-required="true">
<label>From</label>
</div>
<div>
<input type="text" name="subject" ng-model="email.subject" ng-required="true">
<label>Subject</label>
</div>
<div>
<textarea ng-model="email.text" name="text" placeholder="Enter Text Here.."></textarea>
</div>
<button id="emailSubmitBn" type="submit" ng-click="submitEmail()">
Submit
</button>
</form>
<!-- JS -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.11/angular.min.js"></script>
<script type="text/javascript" src="js/app.js"></script>
</body>
</html>
CLIENT SIDE APP.JS
angular.module('myApp', [])
.controller('MainCtrl', function($scope, $http) {
$scope.submitEmail = function() {
console.log("TEST");
//Request
$http.post('/email', $scope.email)
.success(function(data, status) {
console.log("Sent ok");
})
.error(function(data, status) {
console.log("Error");
})
};
});

Categories

Resources