Node.js - How to initialise/define req.body? - javascript

I get the error - "Cannot read property 'score' of undefined" at "var score - req.body.score". In order to do this I'm guessing I need to define and/or initialise 'req.body' (I'm pretty new to Node.js), any idea how I do this?
Here's my Node.JS code as it stands:
var http = require('http');
var express = require('express');
console.log('Game server running...');
http.createServer(function (req, res) {
console.log('Player submitted high-score:');
var score = req.body.score;
console.log(score);
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('_testcb(\'"Your high-score has been submitted."\')');
}).listen(80);
Below is the HTML with the input text field and a submit button:
Your score: <input id="score" name="score" type="text"></input>
<button id="SubmitBtn" type="submit">Submit</button>
And also below is the JavaScript within the HTML (Just in case it helps answer my question):
<script>
$(document).ready(function() {
$('#SubmitBtn').click(function (event) {
$.ajax({
url: 'http://localhost',
data: { score : $("input[name='score']").val() },
dataType: "jsonp",
jsonpCallback: "_testcb",
cache: false,
timeout: 5000,
success: function(data) {
$("#test").append(data);
},
error: function(jqXHR, textStatus, errorThrown) {
alert('Error connecting to the Node.js server... ' + textStatus + " " + errorThrown);
}
});
});
});
Basically, I want to get the input from a input text field called 'score' from a HTML doc, but getting the error "Cannot read property 'score' of undefined" at 'var score - req.body.score'. Guessing I need to initialise/define 'req.body somewhere but I don't know how? Can anyone help me out?
Also, I've found this online about initialising/defining 'res.body', could be useful??
req.on('response', function (res) {
res.body = "";
res.on('data', function (chunk) {
res.body += chunk;
});
res.on('end', function () {
console.log(res.body);
});
});
Thanks

I don’t know whether some “middleware” provides req.body, but to continue down that path:
var http = require('http');
var express = require('express');
var qs = require('querystring');
console.log('Game server running...');
http.createServer(function (req, res) {
console.log('Player submitted high-score:');
var bodyParts = [];
req.on("data", function(part) {
bodyParts.push(part);
});
req.on("end", function() {
var body = Buffer.concat(bodyParts).toString("utf8");
var data = qs.parse(data);
var score = data.score;
console.log(score);
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('_testcb(\'"Your high-score has been submitted."\')');
});
}).listen(80);

The request.body property is populated by the bodyParser middleware, so you have to include that in the node.js app as well
app.use(express.bodyParser())
so
var http = require('http');
var express = require('express');
var app = express();
console.log('Game server running...');
app.use(express.bodyParser())
console.log('Player submitted high-score:');
app.get('/', function(req, res) {
var score = req.body.score;
console.log(score);
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('_testcb(\'"Your high-score has been submitted."\')');
});
app.listen(80);
req is the request, containing data from the current request, and res is the response you send back from the server, so trying to get the data from the input from the respone you send back is not going to work.

Related

Node.js parsing form data using formidable

Hey guys I am new to node, and trying to setup a file/image upload script.
I was able to setup node on my VPS and following this example I also set up the app and it is working great.
https://coligo.io/building-ajax-file-uploader-with-node/
It is using formidable and express
However I'd love to also parse a form where people can add their name and the files get uploaded into a folder containing their names.
I was able to get the folder creation working using mkdirp, however even after many hours of research (formidable api, express api, and more) I can't get the form to parse the name.
I suspect that the upload.js (which sends the data to the node app) does not work.
At the moment a new folder with a random string is created for each upload, but I'd love to be able to parse the entered formname.
Any idea how to get it working? I'd appreciate any help/hints.
app.js
var express = require('express');
var app = express();
var path = require('path');
var formidable = require('formidable');
var fs = require('fs');
var mkdirp = require('mkdirp');
var crypto = require("crypto");
app.use(express.static(path.join(__dirname, 'public')));
app.get('/', function(req, res){
res.sendFile(path.join(__dirname, 'views/index.html'));
});
app.post('/upload', function(req, res){
var ordner = crypto.randomBytes(20).toString('hex');
mkdirp('/home/myfolder/fileupload/'+ordner, function (err) {
if (err) console.error(err)
else console.log(ordner)
});
var form = new formidable.IncomingForm();
form.multiples = true;
form.uploadDir = path.join(__dirname, '/'+ ordner);
form.on('file', function(field, file) {
fs.rename(file.path, path.join(form.uploadDir, file.name + Date.now()+'.jpg'));
});
form.on('field', function(field, userName) {
console.log(userName);
});
form.on('error', function(err) {
console.log('An error has occured: \n' + err);
});
form.on('end', function() {
res.end('success');
});
form.parse(req);
});
var server = app.listen(3000, function(){
console.log('Server listening on port 3000');
});
Thanks
The upload.js is unchanged and I simply added another input to the view.
You can do this by sending the parameters through the POST like so
app.post('/upload/:userName', function(req, res){
var username = req.params.userName
mkdirp('/home/myfolder/fileupload/'+username, function (err) {
if (err) console.error(err)
else console.log(ordner)
});
The rest of your code pretty much stays the same.
EDIT: Your ajax would look something like this
var username = 'GetThisValueFromTheUser'
$.ajax({
url: '/upload'+username,
type: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(data){
console.log('upload successful!');
}
});
Note: You can send parameters by using /:parameter in your POST or GET requests, from then on it is easy to use those parameters however you want.

Redirect image request on NodeJS

Inside my application code, for a specific set of APIs, I'm making a NodeJS request like following, which should return a image as the body. This same request works fine on Postman (and I can see the image).
module.exports = {
getThumbnail: function (thumbnailUrn, env, token, onsuccess){
request({
url: config.baseURL(env) + config.thumbail(thumbnailUrn),
method: "GET",
headers: {
'Authorization': 'Bearer ' + token,
}
}, function (error, response, body) {
// error check removed for simplicity...
onsuccess(body);
});
}
}
The above code run under my own security checks and adds the token header. It works fine (request calls return 200/OK).
Now on my app router I want to respond this as an image, but the output is not being interpreted as an image. Here is what I have:
var dm = require(/*the above code*/);
// express router
var express = require('express');
var router = express.Router();
router.get('/getThumbnail', function (req, res) {
var urn = req.query.urn;
dm.getThumbnail(urn, req.session.env, req.session.oauthcode, function (thumb) {
res.writeHead(200,
{
'Content-Type': 'image/png'
}
);
// at this point, the 'thumb' variable is filled
// but I believe is not properly encoded...
// or maybe the res.end output is missing something...
res.end(thumb, 'binary');
});
});
module.exports = router;
EDIT: as commented by Nodari Lipartiya, this is kind of proxy behaviour ( server(responds with image) -> proxy (node.js/resends to client) -> end user)
I'm not sure what is coming back in thumb, but the following snippet seemed to work for me (bypassing Express for simplicity):
var http = require("http")
var fs = require("fs")
var server = http.createServer(listener)
server.listen(() => {
console.log(server.address().port)
})
var binary = fs.readFileSync("path to local image")
function listener(req, resp) {
resp.writeHead(200,
{
'Content-Type': 'image/png'
}
);
resp.end(new Buffer(binary), "binary")
}
What happens if you wrap it in a Buffer?
If I've understood everything correctly:
I did this
server.js
var fs = require('fs');
var express = require('express');
var app = express();
app.get('/img', function(req, res, next) {
var stream = fs.createReadStream('img.jpeg');
var filename = "img.jpeg";
filename = encodeURIComponent(filename);
res.setHeader('Content-disposition', 'inline; filename="' + filename + '"');
res.setHeader('Content-type', 'image/jpeg');
stream.pipe(res);
});
app.listen(9999, function () {
console.log('Example app listening on port 9999!');
});
proxy.js
var request = require('request');
var express = require('express');
var app = express();
app.get('/img', function(req, res, next) {
console.log('proxy/img');
request({
url: 'http://localhost:9999/img',
method: "GET",
}, function (error, response, body) {
res.end(body, 'binary');
});
});
app.listen(9998, function () {
console.log('Example app listening on port 9998!');
});
req.js
var request = require('request');
request({
url: 'http://localhost:9998/img',
method: "GET",
}, function (error, response, body) {
console.log('body', body);
});
works for me. Please, let me know if you'll need help.

How to make ajax get/post request in express server?

Below is my express server. I am trying to make a get request in ajax, but it turned out failed even though I required jquery at the beginning. It said $ is not defined Other than using jquery ajax, what else can I use to make an API call form RESTful API url?
var express = require('express');
var requestHandler = require('./requestHandler');
var app = express();
var path = require('path');
app.use(express.static(path.join(__dirname, '../client')));
app.get('/homepage', requestHandler.getData);
var port = process.env.PORT || 3000;
app.listen(port);
console.log("Server running at: http://localhost:" + port);
// request handler file:
var express = require('express');
var url = "http://jsonplaceholder.typicode.com/";
module.exports.getData = function (req, res){
$.ajax({
method: 'GET',
url: url+'posts',
success: function(data) {
console.log(data);
res.send(data);
}
});
}
module.exports.getComments = function(userId){
$.ajax({
method: 'GET',
url: url+'/comments',
success: function(data) {
console.log(data);
}
});
}
HTTP GET Request in Node.js Express
var http = require('http');
var options = {
host: 'www.google.com',
path: '/index.html'
};
var req = http.get(options, function(res) {
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers));
// Buffer the body entirely for processing as a whole.
var bodyChunks = [];
res.on('data', function(chunk) {
// You can process streamed parts here...
bodyChunks.push(chunk);
}).on('end', function() {
var body = Buffer.concat(bodyChunks);
console.log('BODY: ' + body);
// ...and/or process the entire body here.
})
});
req.on('error', function(e) {
console.log('ERROR: ' + e.message);
});
You need to understand things like:
expressjs is serverside code so it can't use jquery ajax like that.
jQuery.ajax() can only be used at view when you load your page in the browser.
You need to use some view engines like jade to create templates and use routers to push the view in the browser. When you have your view in the browser then you can make a reference to the script file which can contain your ajax code to let you have posts and comments.
More information.
Try something like this:
function() {
// Simple POST request example (passing data) :
$http.post("/createProject/"+ id +"", {
projectTitle: pTitle,
userID : id
}).
success(function(data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
$scope.getProjects();
console.log("project created");
console.log("this is the response data " + data);
}).
error(function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
};
Also please note. you will call this from an external JavaScript file. One the express server you will only have "routes" and from external javascript files you can perform HTTP calls on those routes.
Update
#Someone, the express framework is very popular to setup a web server in Node. You can use different render engines to render the view and pass information to the user. This is a very simple example from the Express website listening to two urls (/posts and /comments).
var express = require('express');
var app = express();
app.get('/posts', function (req, res) {
res.send('Render posts!');
});
app.get('/comments', function (req, res) {
res.send('Render comments');
});
var server = app.listen(3000, function () {
var host = server.address().address;
var port = server.address().port;
console.log('Example app listening at http://%s:%s', host, port);
});

How to post data from my html page to a listener?

I'm currently designing a UI for an Automated Parking System. I currently need to test if my page sends out data from a form by sending it to a listener. I currently have this code but I'm not sure why it isn't working. Any help would be greatly appreciated.
This is my code that sends the data to a local listener.
<script>
var INPARK = {cardID: $("#ticket_num").val(), lift: 1, floor: 1};
$.ajax({
type:"POST",
url: '192.168.150.148:5007',
contentType:"application/json",
data: JSON.stringify(INPARK)
});
</script>
This is the listener code.
var HOST = '192.168.150.148'; // This should be your IP of 192.168.150.XXX
var PORT = 5007;
var http = require('http');
http.createServer(function (req, res) {
// Only listen for POST requests
if (req.method === 'POST') {
var buffer = '';
req.on('data', function (chunk) {
buffer += chunk;
});
req.on('end', function () {
var path = req.url.substring(0, req.url.indexOf('/', 1)).toUpperCase();
var json;
try {
json = JSON.parse(buffer);
} catch (err) {
//
}
if (path === '/INPARK') {
// Handle INPARK request
console.log(json);
res.write('inpark results');
} else if (path === '/OUTPARK') {
// Handle OUTPARK request
console.log(json);
res.write('outpark results');
} else {
// Do nothing - Bad request
res.write('BAD REQUEST');
}
// Close the connection
res.end();
});
}
}).listen(PORT, HOST, function () {
console.log('Listening at %s:%s', HOST, PORT);
});
Your ajax request is most likely going from port 80 or 443 to 5007, which is a cross domain request, hence it will fail,
If you want to resolve this issue, read up on CORS:
https://en.wikipedia.org/wiki/Cross-origin_resource_sharing,
and JSONP:
https://en.wikipedia.org/wiki/JSONP

Client side javascript doesn't find my url

I would like to develop a client server side with nodejs and javascript/jquery but I am stuck.
I have a big form, user submits and data are send to /getData url and that works perfectly. But my problem now it's when I want to get those data from /getData to my client side.
This is my client file:
var client = {};
client.start = function () {
client.getData();
};
client.cb_get = function () {
var data={};
if (this.readyState == 4 && this.status == 200) {
data= JSON.parse(this.responseText);
alert("We get the data" + JSON.stringify(data, null, 4));
client.chart(data);
} else {
alert("Sorry this page is not allow without processing any form");
}
};
client.get = function(req, cb) {
var xhr = new XMLHttpRequest();
xhr.open("GET", req, true);
xhr.onreadystatechange = cb;
xhr.send();
};
client.getData= function () {
var req="http://localhost:3000/getData";
client.get(req,client.cb_get);
};
client.chart= function (data) {
//Display data as charts using jquery in an other html page.
};
window.onload = setTimeout(client.start, 1);
HTMLElement.prototype.has_class = function (c)
{
return this.className.indexOf(c) >= 0;
};
But I have a 404 error all the time and I don't know why.
my server file :
var express = require('express')
bodyParser =require("body-parser");
routes= require('./router.js');
var app= express();
app.use(express.static(__dirname + '/'));
//Here we are configuring express to use body-parser as middle-ware.
app.use(bodyParser.urlencoded({ extended: false }));
//define our routes
app.get('/', routes.index); //open home page
app.get('/simulation', routes.simulation);
app.get('/chartData', routes.chartData);
app.post('/getData', routes.getData);
//In case of malicious attacks or mistyped URLs
app.all('*', function(req, res){
res.send(404);
})
var server = app.listen(3000, function () {
var host = server.address().address
var port = server.address().port
console.log('Example app listening at http://%s:%s', host, port)
})
my router file:
module.exports.index= function(req, res){
fs.readFile('index.html', function(err, page) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write(page);
res.end();
});
};
module.exports.simulation= function(req, res){
fs.readFile('simulation.html', function(err, page) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write(page);
res.end();
});
};
module.exports.chartData= function(req,res) {
fs.readFile('chartPage.html', function(err, page) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write(page);
res.end();
});
};
module.exports.getData= function(req,res) {
var data= {};
data= req.body;
res.send(JSON.stringify(data, null, 4));
console.log(req.body);
};
So where I am wrong?
Moreover, when I submit, my /getdata page opens (normal due to action= /getData specified in my form tag) but I want to open directly my html page with charts. How can I do that?
Sorry guys for my long post, but I really need help.
Your ajax request does
xhr.open("GET", "http://localhost:3000/getData", true);
your route listens for
app.post('/getData', routes.getData);
notice how you send a GET request and listen for a POST request, it's not the same thing, so you end up in the 404 route instead.
You either have to change the ajax request, and send a POST request, or the route and listen for a GET request.

Categories