I am trying to write a simple piece of code using NodeJS to get the JSON back from the stack exchange API.
This is the API I am targetting- https://api.stackexchange.com/2.2/users?order=desc&sort=reputation&inname=donal%20rafferty&site=stackoverflow
And here is my code:
var https = require('https'); //Use NodeJS https module
function getUserDataByName(userName, callback){
var stackOverflowUserURL = 'https://api.stackexchange.com/2.2/users?order=desc&sort=reputation&inname='+encodeURIComponent(userName)+'&site=stackoverflow';
https.get(stackOverflowUserURL, function(response){
console.log("headers: ", response.headers);
if (response.statusCode == 200) {
var jsonString = '';
response.on('data', function (chunk) {
jsonString += chunk;
});
response.on('end', function () {
console.log((jsonString));
callback(JSON.stringify(jsonString));
});
}
else{
//error
console.log("Error");
}
});
}
However when I run this the data always comes back in a state of garbage like text like the following:
\"\u001f�\b\u0000\u0000\u0000\u0000\u0000\u0004\u0000uR�n�0\f��B���ږ\u0013�2\u0010�R�m�u\\u0018\\u0004ڢ\\u001d!��Jr=�ȿ�vS\\u0004\\u0005������H����C��7ր�Q�n��\u0012\u0014{g�\\"��]����+zV\u001f����(V��%a�n|�)QU�.O�\u000e\u0012�Ѹ\u0005��\u0003\u00130a\u0006B��S�Ө�����C^��bw�I\u000bC��b�\u0017e�\u0013�q�\\"D��lO`���#^\nq\u0017|���ի�������?pFz�i�R\u000f�,[�pu�{x�\b~k��LUV��\u0012\u00194�l\u000e�ڕ\rW��\u001c���*�\u001a�9�\u001e�Q+�Q��>���o��;a'\btI�b/��
\u0007�CK̲���\u0000�jۯ����\u0003g|�\u0003�\u0002\u0000\u0000\
I'm assuming there is something wrong with my encoding/decoding but I can't figure out what to do to fix this?
You need to decode the response as it's gzipped
var https = require('https'); //Use NodeJS https module
var zlib = require("zlib");
function getUserDataByName(userName, callback){
var stackOverflowUserURL = 'https://api.stackexchange.com/2.2/users?order=desc&sort=reputation&inname='+encodeURIComponent(userName)+'&site=stackoverflow';
https.get(stackOverflowUserURL, function(response){
console.log("headers: ", response.headers);
console.log(response.statusCode)
if (response.statusCode == 200) {
var gunzip = zlib.createGunzip();
var jsonString = '';
response.pipe(gunzip);
gunzip.on('data', function (chunk) {
jsonString += chunk;
});
gunzip.on('end', function () {
console.log((jsonString));
callback(JSON.stringify(jsonString));
});
gunzip.on('error', function (e) {
console.log(e);
});
}
else{
//error
console.log("Error");
}
});
}
Related
I am new to Node.js and JavaScript and I was hoping to get some help after searching and being unable to find a solution.
I am trying to send a JSON object to the Node.js server containing an array of 2 elements (longitude and latitude) using the XMLHttpRequest method. This is the Client-side JavaScript code:
function getLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var location = [position.coords.latitude, position.coords.longitude];
console.log(location);
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://localhost:3000/locationdata', true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onload = function () {
console.log(this.responseText);
};
xhr.send(location);
});
} else {
console.log('Geolocation is not supported by this browser.');
}
}
The server receives the object without any issue. However, when I try to send the object back to the client, I get an undefined value as the response. Here is the Node.js script:
var html =
fs.readFile(__dirname + '\\public\\index.html', function(err, data) {
if (err){
throw err;
}
htmlFile = data;
});
var server = http.createServer(function (request, response) {
if (request.url == "/") {
response.writeHead(200, {"Content-Type": "text/html"});
response.write(htmlFile);
break;
};
if (request.method == 'POST' && request.url == "/locationdata") {
var postdata = '';
var body = '';
request.on('data', function (data) {
body += data;
});
request.on('end', function() {
var postdata = body;
console.log(postdata);
});
response.writeHead(200, {"Content-Type": "application/json"});
response.write(JSON.stringify(postdata));
}
response.end();
});
server.listen(3000);
It might be that I am sending the response before the actual request has ended but I am not sure. Any ideas?
You are not waiting for the request data before responding, which causes you to respond with nothing. Do this instead:
if (request.method == 'POST' && request.url == "/locationdata") {
var body = '';
request.on('data', function (data) {
body += data;
});
request.on('end', function() {
response.writeHead(200, {"Content-Type": "application/json"});
response.end(body);
});
return;
}
I am trying to pass a variable to my Ajax send and read it in Node without using a framework. I am not trying to return the value back to the DOM, I just need to read the value passed to Node.js. Here is what I have:
Ajax:
const XHR = new XMLHttpRequest();
XHR.open('POST', document.url, true);
XHR.setRequestHeader('X-Requested-load', 'XMLHttpRequest2');
XHR.send(`password=${password}`);
Nodejs:
const QS = require('querystring');
let password = QS.parse(req.body);
req.on('data', (data) => {
password = QS.parse(data);
});
console.log(password);
Hope this will help you:
http.createServer(function (request, response) {
if (request.method == 'POST') {
// save all data received
var postdata = '';
// receiving data
request.on('data', function(chunk) {
postdata += chunk;
// Avoid too much POST data
if (postdata.length > 1e6)
request.connection.destroy();
});
// received all data
request.on('end', function() {
var post = qs.parse(postdata);
// handle post by accessing
// post['password']
// response.send(process(post['password']));
});
} else {
console.log("Non POST request received at " + request.url);
}
}).listen();
In your example you are trying to access password out of the callback where this data is provided.
const QS = require('querystring');
let password = QS.parse(req.body);
req.on('data', (data) => {
password = QS.parse(data);
//async. access data here
console.log(password);
});
I have a file called node.js:
var net = require('net');
var crypto = require('crypto');
//sjcl
var sjcl = require('./sjcl');
//retrive fb profile
var loadFb = require('./loadFb.js');
var loadFeed = require('./loadFeed.js');
//read json user file
var fs = require('fs');
var text = fs.readFileSync(__dirname + '/users','utf8');
var HOST = 'localhost';
var PORT = 7000;
net.createServer(function(sock) {
// We have a connection - a socket object
console.log('CONNECTED: ' + sock.remoteAddress +':'+ sock.remotePort);
// Add a 'data' event handler to this instance of socket
sock.on('data', function(data) {
console.log('User request profile of: ' + data);
//var date = (data.toString()).split("***");
//var from = date[1];
loadFb(extendetPath, function(pageData)
{
loadFeed(extendetPath2, function(pageData2)
{
var fs = require('fs');
var profileText = fs.readFileSync('/tmp/profile','utf8');
console.log(profileText);
sock.write(profileText);
});
});
});
// Add a 'close' event handler to this instance of socket
sock.on('close', function(data) {
console.log('CLOSED: ' + sock.remoteAddress +' '+ sock.remotePort);
});
}).listen(PORT);
console.log('Server listening on ' + HOST +':'+ PORT);
function returnKeyFromUser(id)
{
//text
var trovata = false;
var dati = JSON.parse(text);
for(var i=0; i<dati.friendlist.friend.length && trovata==false; i++)
{
var user = (dati.friendlist.friend[i].username).replace("\n","");
var userID = (id).replace("\n","");
if(user==userID)
{
trovata=true;
return ((dati.friendlist.friend[i].publicKey).toString()).replace("\n","");
}
}
if(trovata==false)
return null;
}
There is a small http server that receives a facebook username and what he have to do is retrieve 2 page:
a graphapi with the profile information, and a graphapi with the feed informations of a facebook profile
I copy the other two files:
var https = require('https');
module.exports = function(path, callback) {
var options = {
host: 'graph.facebook.com',
port: 443,
path: (path.toString()).replace("\n",""),
method: 'GET'
};
var req = https.get(options, function(res) {
var pageData = "";
if((path.toString()).indexOf("/")==0 && (path.toString()).indexOf("/GET /`HTTP/")!=0)
//for load only (I hope facebook profile)
{
console.log(options);
res.setEncoding('utf8');
res.on('data', function (chunk) {
pageData += chunk;
});
res.on('end', function()
{
var fs = require('fs');
fs.writeFile("/tmp/profile", pageData, function(err) {
if(err) {
console.log(err);
} else {
console.log("The file was saved!");
}
});
//callback(pageData);
return;
});
}
});
};
3° file
var https = require('https');
module.exports = function(path, callback) {
var options = {
host: 'graph.facebook.com',
port: 443,
path: (path.toString()).replace("\n",""),
method: 'GET'
};
var req = https.get(options, function(res) {
var pageData = "";
if((path.toString()).indexOf("/")==0 && (path.toString()).indexOf("/GET / HTTP/")!=0) //for load only (I hope facebook profile)
{
console.log(options);
res.setEncoding('utf8');
res.on('data', function (chunk) {
pageData += chunk;
});
res.on('end', function()
{
var fs = require('fs');
fs.appendFile('/tmp/profile', "***"+pageData, function (err) {
if (err) throw err;
console.log('It\'s saved!');
});
callback(pageData);
});
}
});
};
I don't know If there is a way to call the two file in the first file node.js but what I done is this: (to call from node.js the fist file, and from the second file call the third)
in node.js file I call the first file loadFb.js with this command:
loadFb(extendetPath, function(pageData)
{
This call saves a file on my tmp profile directory and inside I call the other file loadFeed that appends some text.
After that I have to send the entire information to the client but I have a mistake.
In order the nodejs correctly call loadFb and he write tmp - profile, than he call loadFeed
but before appending the information the node call back to the client only the half of informations that I need.
I'm not a good nodejs programmer, this is a work for my thesis.
Can someone help me?
Let's look at the following code:
res.on('end', function()
{
var fs = require('fs');
fs.appendFile('/tmp/profile', "***"+pageData, function (err) {
if (err) throw err;
console.log('It\'s saved!');
});
callback(pageData);
});
What it does it runs the asynchronous method appendFile and immediately after that calls callback. So when the code in the callback is executed, the file is not updated yet. You need to move the callback(pageData); to the appendFile's callback. And you need to review you code keeping this in mind because I see that the same fix should be made in another file so maybe there are some similar places as well.
This question already has answers here:
How can I do Base64 encoding in Node.js?
(7 answers)
Closed 9 years ago.
I'm a node.js newbie stuck trying to implement base64 encoding. My server doesn't seem to receive/process the base64 message. Code below:
Server:
var http = require('http');
http.createServer(function (req, res) {
req.on('data',function(b) {
console.log("HEY!"); // <--- Never gets called
var content = new Buffer(b, 'base64').toString('utf8')
console.log("CLIENT SAID: "+content);
var msg = JSON.parse(content);
// do stuff and respond here...
});
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
Client:
var http = require('http');
var options = {
hostname : 'localhost',
port : 1337,
method : 'POST'
};
var req = http.request(options, function(res) {
res.setEncoding('base64');
res.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
// write data to request body
var msg = {'name':'Fred','age':23};
var msgS = JSON.stringify(msg);
req.write(msgS,'base64');
req.end();
Any ideas what I'm doing wrong?
I came up with a fix. I noticed when using req.write(data, 'base64'); that the request never ended. I instead created a buffer that was base64 encoded, then wrote it to the request.
These exact snippets were tested localhost:
Client:
var http = require('http');
var options = {
hostname: 'localhost',
port: 1337,
method: 'POST'
};
var req = http.request(options, function (res) {
res.setEncoding('base64');
res.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
var msg = {
'name': 'Fred',
'age': 23
};
var msgS = JSON.stringify(msg);
var buf = new Buffer(msgS, 'base64');
req.write(msgS);
req.end();
Server:
var http = require('http');
http.createServer(function (req, res) {
var content = '';
req.on('data', function (chunk) {
content += chunk;
});
req.on('end', function() {
content = content.toString('base64');
console.log(content);
//content returns {"name": "Fred","age": 23};
res.end();
});
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
Aside from those things, I noticed these errors in your code.
req.on('data',function(b) {
var content = new Buffer(b, 'base64').toString('utf8')
});
Note that b in this case is actually already a buffer. You should use b.toString('base64');. Also note that b is actually only fragments of the data. You should instead collect the data of b, then listen to the end event to finally do something with the data. In your case with req.write(data, 'base64');, the end would never fire, leading to a hangup instead of the event firing.
This is how you'd collect data:
var content = '';
req.on('data', function(b) {
content += b;
});
req.on('end', function() {
//do something with content
});
I have written a http server using node js
var sys = require("sys"),
http = require("http"),
url = require("url"),
path = require("path"),
fs = require("fs");
http.createServer(function(request, res) {
var parsed_url = url.parse(request.url);
var uri = parsed_url.pathname;
if(uri === "/test"){
res.writeHead(200, {'Content-Type': 'text/javascript'});
request.addListener('data', function (chunk) {
var data = eval("(" + chunk + ")");
console.log(data[0].id);
})
request.addListener('end', function() {
console.log('end triggered');
res.write("Post data");
res.end();
});
}
}).listen(8080);
and i am trying to send back response of ajax request but i am unable to receive any response. Here is the code for ajax request ,
var myhttp = new XMLHttpRequest();
var url = "http://localhost:8080/test";
var data = [{"a":"1"},{"b":"2"},{"c":"3"}];
var dataJson = JSON.stringify(data);
myhttp.open('POST', url, true);
myhttp.send(dataJson);
myhttp.onreadystatechange = function() {
if ((myhttp.readyState == 4) && (myhttp.status == 200)){
alert(myhttp.responseText);
}
else if ((myhttp.readyState == 4) && (myhttp.status != 200))
{
console.log("Error in Connection");
}
Can anyone help me what i am doing wrong ...
Thanks
Vinay
Your code is almost right but on your code sample you have
console.log(data[0].id)
the data object has no property id so if you only have
console.log(data[0])
there you have a response like
{ a: '1' }
therefore you can access the property a by doing
console.log(data[0].a);
UPDATED Updated with a full example
One more thing is that you are using eval and node comes with JSON.parse bundle with it so the snippet below is how i made it work
File: app.js
var sys = require("sys"),
http = require("http"),
url = require("url"),
path = require("path"),
fs = require("fs");
http.createServer(function(request, res) {
var parsed_url = url.parse(request.url);
var uri = parsed_url.pathname;
if(uri === "/test"){
res.writeHead(200, {'Content-Type': 'text/javascript'});
request.addListener('data', function (chunk) {
// removed this - eval("(" + chunk + ")");
var data = JSON.parse(chunk);
console.log(data[0].a);
})
request.addListener('end', function() {
console.log('end triggered');
res.write("Post data");
res.end();
});
} else if(uri === "/") {
fs.readFile("./index.html",function(err, data){
if(err) throw err;
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(data);
});
}
}).listen(8080);
On the same directory create a file index.html with the following:
<html>
<head>
<script type="text/javascript" charset="utf-8">
var myhttp = new XMLHttpRequest();
var url = "http://localhost:8080/test";
var data = [{"a":"1"},{"b":"2"},{"c":"3"}];
var dataJson = JSON.stringify(data);
myhttp.open('POST', url, true);
myhttp.send(dataJson);
myhttp.onreadystatechange = function() {
if ((myhttp.readyState == 4) && (myhttp.status == 200)){
alert(myhttp.responseText);
}
else if ((myhttp.readyState == 4) && (myhttp.status != 200))
{
console.log("Error in Connection");
}
}
</script>
</head>
<body>
</body>
</html>
That is a complete working example of what you want.
With regards to the same origin policy issues you were having is mainly due to the fact that you cant POST data between 2 different domains via ajax unless you use some tricks with iframes but that is another story.
Also i think is good for anyone to understand the backbone of a technology before moving into frameworks so fair play to you.
good luck
You have to read the data in a different way. Posted data arrives on a node server in chunks (the 'data' event), that have to be collected until the 'end' event fires. Inside this event, you are able to access your payload.
var body = '';
request.addListener('data', function (chunk) {
body += chunk;
});
request.addListener('end', function() {
console.log(body);
res.write('post data: ' + body);
});
Additionaly, there seem to be some issues with your client-side code (especially concerning the status-code checks), but i can't really help you with those as i always work with frameworks like jQuery to manage async requests.
If you want to build reliable node.js servers for web use, i highly recommend the high-performance HTTP-Framework Express. It takes away alot of the pain when developing a web-based server application in node and is maintained actively.