Ajax with form method as post in node.js - javascript

I have an issue with Ajax in a form with node.js, I'm developing a simple node.js currency converter application and populating the data on the frontend (HTML) using Ajax. However it's not working, any help is seriously appreciated. Thanks.

1. Frontend
Change this
xmlhttp.open("GET","http://localhost:9099/", true);
to
xmlhttp.open("POST","http://localhost:9099/", true);
as your backend server accepts POST for getting the answer.
2. Backend
Remove response.end and response.writeHead from bottom, and move it to where you are calculating store.
Your final code:
http.createServer(function(request, response) {
switch (request.method) {
case 'POST':
if (request.url === "/") {
var requestBody = '';
request.on('data', function(data) {
requestBody += data;
if (requestBody.length > 1e7) {
response.writeHead(413, {
'Content-Type': 'text/plain'
});
response.end('Request Entity is too large');
}
});
request.on('end', function(data) {
console.log(requestBody);
var formData = qs.parse(requestBody);
var requestBofy = '';
// I renamed the callback parameter to response2
https.get('https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml?8f65cd5d1af1727c40d2a89a31c6a0f1', function(response2) {
if (response2.statusCode >= 200 && response2.statusCode < 400) {
response2.on('data', function(data_) {
requestBofy += data_.toString();
});
response2.on('end', function() {
console.log(requestBofy);
parser.parseString(requestBofy, function(err, result) {
console.log('FINISHED', err, result);
var xml = requestBofy;
var parseString = require('xml2js').parseString;
parseString(xml, function(err, result) {
var jFile = JSON.stringify(result);
var parsedResponse = JSON.parse(jFile);
var rateHUF = parsedResponse['gesmes:Envelope']['Cube'][0]['Cube'][0]['Cube'][6]['$'].rate;
var rateINR = parsedResponse['gesmes:Envelope']['Cube'][0]['Cube'][0]['Cube'][22]['$'].rate;
var store = 'No value';
if (formData.vSelectedValue == 'HUF' && formData.vSelectedValue2 == 'INR') {
store = Math.round(formData.vFirstNo * (rateINR / rateHUF));
} else {
store = Math.round(formData.vFirstNo * (rateHUF / rateINR));
}
// Your response should end here
response.writeHead(200, {
"Content-Type": "text/html"
});
response.end('Your Answer: ' + store);
});
});
});
}
});
});
} else {
response.writeHead(404, {
'Content-Type': 'text/plain'
});
response.end('404 - Page not found');
}
break;
case 'GET':
if (request.url === "/") {
getFileContent(response, 'public/home.html', 'text/html');
} else {
response.writeHead(404, {
'Content-Type': 'text/plain'
});
response.end('404 - Page not found');
}
break;
default:
response.writeHead(404, {
'Content-Type': 'text/plain'
});
response.end('404 - Page not found');
}
}).listen(9099);

Related

How to fix SSL error with NodeJS HTTPS server?

I'm new to Stack Overflow and this is my first question, so please bear with me. I never had to ask a question until I had a problem and couldn't find a solution. Anyways, my problem is my Node JS HTTPS server that I use to host my website has a problem where when the client requests a resource such as a video or an image, it's a 50% chance that the resource will properly load for the client. The times it doesn't load I get an SSL error in the console (for example, net::ERR_SSL_PROTOCOL_ERROR 200 (OK)). Sometimes it will load, sometimes it won't. I don't know if I have a misconfiguration with my server or not, but I need to get this fixed. I need the resource to load for the client 100% of the time. Any help would be great.
Here's how my server is configured.
const reqHandler = (req, res) => {
let body = '';
req.on('data', chunk => body += chunk.toString());
req.on('end', () => {
var path = req.url.split('?')[0];
var query = req.url.split('?')[1] || '';
res.statusCode = 200; // Assume a good request unless otherwise indicated
if (path.split('/').slice(-1)[0] === '') { // If client requests folder
if (existsSync(`./${root}${path}index.js`)) { // node-http has priority
let type = readFileSync(`./${root}${path}index.js`, 'utf-8').split('\n')[0];
type = type.replace('//', '').trim();
if (type === 'node-http') {
try {
delete require.cache[require.resolve(`./${root}${path}index.js`)];
require(`./${root}${path}index.js`).callback(req, res, body, query);
} catch (e) {
res.write(`Node HTTP exception: ${e.message}`);
res.end();
}
return;
}
} else { // Otherwise, fallback to index.html
path = path + 'index.html';
}
} else { // If the client didn't request a folder
if (path.split('.').length === 1) { // No extension? No problem!
// See if it's a folder
if (existsSync(`./${root}${path}/`)) { // Redirect, if exists
res.statusCode = 301;
res.setHeader('Location', path + '/');
res.end();
return;
} else { // If not folder, assume try to find it
var extensions = getType('get-extensions');
for (var i of extensions) {
if (existsSync(`./${root}${path}.${i}`)) {
path = `${path}.${i}`;
break;
}
}
}
}
var extension = path.split('.').slice(-1)[0];
// node-http
if (extension === 'js') {
if (!existsSync(`./${root}${path}`)) {
res.statusCode = 404;
res.end();
return;
}
let type = readFileSync(`./${root}${path}`, 'utf-8').split('\n')[0];
type = type.replace('//', '').trim();
if (type === 'node-http') {
try {
delete require.cache[require.resolve(`./${root}${path}`)];
require(`./${root}${path}`).callback(req, res, body, query);
} catch (e) {
res.write(`Node HTTP exception: ${e.message}`);
res.end();
}
return;
}
}
if (extension === 'ws') {
// Websocket connection
return;
}
// videos
if (extension === 'mp4') {
var vidPath = `./${root}${path}`;
readFile(vidPath, (err, data) => {
if (err) {
if (err.code === 'ENOENT') {
res.statusCode = 404;
res.end('404 Not Found');
}
res.end();
return
} else {
var stats = statSync(vidPath);
let size = stats.size;
let chunkSize = 10 ** 6; // 1 megabyte (1,000,000 bytes)
let start = req.headers.range ? Number(req.headers.range.replace(/\D/g, "")) : 0;
let end = Math.min(start + chunkSize, size - 1);
let contentLength = end - start + 1;
res.setHeader('Content-Range', `bytes ${start}-${end}/${size}`);
res.statusCode = 206;
res.writeHead(206, {
'Content-Range': `bytes ${start}-${end}/${size}`,
'Content-Type': 'video/mp4',
'Content-Length': contentLength,
'Accept-Ranges': 'bytes',
'Date': new Date().toUTCString()
});
let stream = createReadStream(vidPath, {start, end});
stream.pipe(res);
}
});
return;
}
}
readFile(`./${root}${path}`, (err, data) => {
if (err) {
if (err.code === 'ENOENT') {
res.statusCode = 404;
res.end('404 Not Found');
}
} else {
let type = getType(path.split('.').slice(-1)[0]);
if (type !== null) {
res.setHeader('Content-Type', type);
}
res.end(data);
}
});
});
}
// Redirect HTTP traffic to HTTPS
http.createServer((req, res) => {
if (req.headers.host === 'domain.com') {
let redirectUrl = `https://${req.headers.host}${req.url}`;
res.statusCode = 301;
res.setHeader('Location', redirectUrl);
res.end();
return;
}
reqHandler(req, res);
}).listen(80);
// HTTPS server
const server = https.createServer({
cert: readFileSync('/path/to/cert.pem').toString(),
key: readFileSync('/path/to/key.pem').toString(),
ca: readFileSync('/path/to/chain.pem').toString()
}, reqHandler);
server.listen(443);

Call function with request options from another function always empty

I have a code like below. I am running a calling a function searchApiData. In searchApiData, when I log data in console I can see values of body. But when I see from exports.readData console.log(returnData), the value is always empty. Anyone know how I can get the data of the body in searchApiData?
exports.readData = functions.https.onRequest(async (req, res) => {
var returnData = "";
for (var a = 0; a < emailList.length; a++) {
returnData = searchApiData(emailList[a]);
console.log(returnData);
}
})
function searchApiData(email) {
fsData = "";
const options = {
method: 'GET',
json: true,
url: FS_URL + 'api/lookup?f=email&q='+email+'&entities=contact',
headers: {
"Authorization": "Token token=" + FS_API_KEY,
"Content-Type": "application/json"
}
};
//call the request
request(options, function(error, response, body) {
if(!error && response.statusCode == 200){
console.log(body);
fsData = body;
} else{
console.log(error);
}
});
return fsData;
}

.ajax call never returns

I'm using Express and Node. I've got some code that is posting JSON to another service that is adding it in a database.
The logic is doing what it is supposed to do, but the ajax call I am making is never returning, in the 'Network' tab in Chrome Dev tools it always shows as 'Pending' and eventually errors out with net::ERR_EMPTY_RESPONSE.
Can anyone tell me where I am going wrong?
Ajax Call
$.ajax
({
type: "POST",
url: "/order",
contentType: 'application/json',
data: orderDataJson,
success: function () {
alert("success!");
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert("Something went wrong checking out!\n" + textStatus + "\n" + errorThrown);
}
});
This above routes to /order, which in turn posts the data to the other service:
app.post("/order", function(req, res, next)
{
var options = {
uri: endpoints.ordersUrl + "order",
method: 'POST',
json: true,
body: req.body
};
request(options, function(error, response, body) {
if (error !== null )
{
return;
}
if (response.statusCode == 200 && body != null && body != "")
{
if (body.error)
{
res.status(500);
res.end();
return;
}
res.end(); // UPDATED AFTER COMMENT
return;
}
console.log(response.statusCode);
});
});
This is the relevant code in the other service (it's correctly adding the content in the database)
if (request.method == 'POST')
{
switch (path)
{
// Add a new order
case "/order":
var body = '';
request.on('data', function (data) {
body += data;
});
request.on('end', function () {
var orderData = JSON.parse(body);
// Insert into orders table
var saleDate = getDate();
var ordersQuery = "INSERT into orders (customerId, saledate)" +
" VALUES (" + orderData.customerId +",'" + saleDate + "')";
db.query(ordersQuery, function(err, result)
{
if (err)
{
throw err;
}
var orderId = result.insertId;
// Insert order details
for (var i=0; i < orderData.order.length; i++)
{
var productId = orderData.order[i].productId;
var quantity = orderData.order[i].quantity;
var orderDetailsQuery = "INSERT into orderdetails (orderID, productID, quantity)" +
"VALUES (" + orderId + "," + productId + "," + quantity +")";
db.query(orderDetailsQuery, function(err, result)
{
if (err)
{
throw err;
}
});
}
});
response.writeHead(200, {
'Access-Control-Allow-Origin': '*'
});
});
break;
Try to add this in your error block:
if (error !== null ) {
res.status(500).send('Internal server error!');
return;
}
I got this fixed. The issue seem to be that express 'middleware' function should have been:
app.post("/order", function(req, res, body)
as opposed to:
app.post("/order", function(req, res, next)
From the expressjs docs:
If the current middleware function does not end the request-response cycle, it must call next() to pass control to the next middleware function. Otherwise, the request will be left hanging.

How to make a GET and POST request to an external API?

var Attendance = require('../../../collections/attendance').Attendance;
var moment = require('moment');
module.exports = function(app) {
app.get('/api/trackmyclass/attendance', function(req, res) {
var data = req.body;
data['user'] = req.user;
Attendance.getByUser(data, function(err, d) {
if (err) {
console.log('This is the err' + err.message);
res.json(err, 400);
} else {
var job = d['attendance'];
if (typeof job != undefined) {
res.json(job);
console.log('This is it' + job['status']);
} else
res.json('No data Present', 200);
}
});
});
app.post('/api/trackmyclass/attendance', function(req, res) {
var data = req.body;
data['user'] = req.user;
Attendance.create(data, function(err, d) {
if (err) {
console.log('This is the err' + err.message);
res.json(err, 400);
} else {
var attendance = d['attendance'];
if (typeof job != undefined) {
console.log('Attendance record created' + attendance);
res.json(attendance);
} else
res.json('No data Present', 200);
}
});
});
}
This is the api code I to which I need to make the GET and POST request. But I have no idea how to do it.
It looks like your code is using express which would normally be good for building and API for your app. However to make a simple request to a third party api and staying in node.js why not try the request module which is great. https://www.npmjs.org/package/request
Your example does not show what the path of the request is or if you need any additinal headers etc but here is a simple example of a GET request using request.
var request = require('request');
function makeCall (callback) {
// here we make a call using request module
request.get(
{ uri: 'THEPATHAND ENDPOINT YOU REQUEST,
json: true,
headers: {
'Content-Type' : 'application/x-www-form-urlencoded',
}
},
function (error, res, object) {
if (error) { return callback(error); }
if (res.statusCode != 200 ) {
return callback('statusCode');
}
callback(null, object);
}
);
}
or jquery .ajax from a front end client direcct to your path
$.ajax({
url: "pathtoyourdata",
type: "GET",
})
.done(function (data) {
//stuff with your data
});

Upload images to twitter API from node.js

I'm attempting to post an image onto the twitter api, v1.1
I've tried just about all the example out there, and nothing seems to be able to post it.
include Posting images to twitter in Node.js using Oauth
I'm using the oauth library mentioned there, and I also had jsOauth, which I thought I'd give a shot according to https://gist.github.com/lukaszkorecki/1038408
Nothing has worked, and at this point I'm starting to lose hope on whether I can even do this.
function postStatusWithMedia(status, file) {
var err = new Object();
if(fs.existsSync(file) === false) {
err.message = "File not found :(";
parseTwitterError(err);
} else {
var oauth = OAuth(options = {
"consumerKey": consumer_key,
"consumerSecret": consumer_secret,
"accessTokenKey": access_token,
"accessTokenSecret": access_token_secret
});
callbacks = {
onSuccess : function() {
console.log('upload worked!')
},
onFailure : function() {
console.log('upload failed!');
console.dir(arguments);
}
},
uploadData = {
'status' : status,
'media' : Base64.encode(fs.readFileSync(file))
};
oauth.post('https://api.twitter.com/1.1/statuses/update_with_media.json',uploadData, callbacks.onSuccess, callbacks.onFailure);
return false;
}
}
If it can't be done, can you please explain why?
Otherwise, anything that could lead me to the right direction would be great.
var fs = require('fs');
var request = require('request');
var FormData = require('form-data');
var utf8 = require('utf8');
// Encode in UTF-8
status = utf8.encode(status);
var form = new FormData();
form.append('status', status)
form.append('media[]', fs.createReadStream(file));
// Twitter OAuth
form.getLength(function(err, length){
if (err) {
return requestCallback(err);
}
var oauth = {
consumer_key: consumer_key,
consumer_secret: consumer_secret,
token: access_token,
token_secret: access_token_secret
};
var r = request.post({url:"https://api.twitter.com/1.1/statuses/update_with_media.json", oauth:oauth, host: "api.twitter.com", protocol: "https:"}, requestCallback);
r._form = form;
r.setHeader('content-length', length);
});
function requestCallback(err, res, body) {
if(err) {
throw err;
} else {
console.log("Tweet and Image uploaded successfully!");
}
}
I ended up using request and node-form-data to manually construct a multipart/form-data request and send it with the status request, utf8 was for encoding the status into UTF-8, not doing so caused issues with '<3' and other characters.
I have not tested these code.Its from my colleague.sure the code is working.
Perhaps this will help.
//twitter_update_with_media.js
(function() {
var fs, path, request, twitter_update_with_media;
fs = require('fs');
path = require('path');
request = require('request');
twitter_update_with_media = (function() {
function twitter_update_with_media(auth_settings) {
this.auth_settings = auth_settings;
this.api_url = 'https://api.twitter.com/1.1/statuses/update_with_media.json';
}
twitter_update_with_media.prototype.post = function(status, imageUrl, callback) {
var form, r;
r = request.post(this.api_url, {
oauth: this.auth_settings
}, callback);
form = r.form();
form.append('status', status);
return form.append('media[]', request(imageUrl));
};
return twitter_update_with_media;
})();
module.exports = twitter_update_with_media;
}).call(this);
next file
//upload_to_twitter.js
var tuwm = new twitter_update_with_media({
consumer_key: TWITTER_OAUTH_KEY,
consumer_secret: TWITTER_OAUTH_SECRET,
token: access[0],
token_secret: access[1]
});
media_picture.picture = imageURL;
if (media_picture.picture) {
console.log('with media upload');
request.head(media_picture.picture,
function (error, response, body) {
if (!error && response.statusCode == 200) {
var image_size = response.headers['content-length'];
if (image_size > 2000000) { // 2mb max upload limit
console.log('greater than 2mb');
sendMessageWithoutImage(err, req, res, next, twit, wallpost, access);
} else {
console.log('less than 2mb');
console.log('twitter text', content);
tuwm.post(content, media_picture.picture, function(err, response) {
if (err) {
console.log('error', err);
return next(err);
}
error_parse = JSON.parse(response.body);
console.log('with media response', response.body);
if (error_parse.errors) {
console.log('have errors', error_parse);
res.json({
status: 500,
info: error_parse.errors[0].code + ' ' + error_parse.errors[0].message
});
} else {
res.json({
status: 200,
info: "OK",
id: response.id
});
}
});
}
}
});

Categories

Resources