nodejs callback not work - json

it is the code
var http = require('http');
var request = require("request");
function getData(city, callback){
var urlData = 'http://api.openweathermap.org/data/2.5/weather?q='+city;
callback.write("urlRequest : "+urlData+"\n");
request(urlData, function(error, response, body, callback) {
if(callback && typeof(callback) === "function")
callback.write(body);
});
}
// create http server
http.createServer(function (req, res) {
var query = require('url').parse(req.url).query;
var app = require('querystring').parse(query).city;
// content header
res.writeHead(200, {'Content-Type': 'text/plain'});
if(app)
getData(app, res);
else
res.write("Use url:port?city=xxxx");
res.end();
}).listen(8124);
console.log('Server running at 8124');
I need to print what I get, I tried to use a callback but did not succeed. I do not understand what is wrong. I think the error is in this line or the function is wrong
request(urlData, function(error, response, body, callback) {

Change the name of the second parameter of the getData function to something different (callback -> res). You have a names collision inside of the request call (callback is a function and you want to access the res variable).
By the way, if the request is asynchronous, it's not going to work, because you call res.end() before the res.write() is called.
Edit:
var http = require('http');
var request = require("request");
function getData(city, res){ // Here
var urlData = 'http://api.openweathermap.org/data/2.5/weather?q='+city;
res.write("urlRequest : "+urlData+"\n"); // Here
request(urlData, function(error, response, body, callback) {
if(callback && typeof(callback) === "function")
res.write(body); // Here
res.end(); // Here
});
}
// create http server
http.createServer(function (req, res) {
var query = require('url').parse(req.url).query;
var app = require('querystring').parse(query).city;
// content header
res.writeHead(200, {'Content-Type': 'text/plain'});
if(app) {
getData(app, res);
}
else {
res.write("Use url:port?city=xxxx");
res.end(); // Here
}
}).listen(8124);
console.log('Server running at 8124');

Related

fs.readFile() returns undefined [duplicate]

This question already has answers here:
Returning a value from callback function in Node.js [duplicate]
(4 answers)
How do I return the response from an asynchronous call?
(41 answers)
Closed 2 years ago.
i'm trying to display a html page creating a node http server, when i try to take the code of the html file it returns undefined, this is the code...
var http = require('http');
var fileContent = function(path, format) {
var fs = require('fs');
fs.readFile(path, format, function(error, contents) {
if (error) throw error;
return contents;
});
}
var server = http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
page = fileContent('./page.html','utf8');
console.log(page);
res.end(page);
}).listen(8080);
i printed the error,
[Error: ENOENT: no such file or directory, open './page.html'] {
errno: -2,
code: 'ENOENT',
syscall: 'open',
path: './page.html'
}
the two files are in the same directory
Firstly, fs.readFile is asynchronous function. Which means is not returning the answer instantly or blocks the thread to wait for answer. Instead it requires a callback to let you know when answer is ready.
Secondly, I suggest using path module to merge __dirname (the directory name of the current module) and file name to make absolute file paths.
I will provide 3 solutions using different methods.
Solution 1. Using callback method
var http = require('http');
var fs = require('fs');
var path = require('path');
var fileContent = function(path, format, cb) {
fs.readFile(path, format, function(error, contents) {
if (error) throw error;
cb(contents);
});
}
var server = http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
fileContent(path.join(__dirname, 'page.html'), 'utf8', function (page) {
console.log(page);
res.end(page);
});
}).listen(8080);
Solution 2. Promises using .then
var http = require('http');
var fs = require('fs');
var path = require('path');
var fileContent = function(path, format) {
return new Promise(function (resolve, reject) {
fs.readFile(path, format, function(error, contents) {
if (error) reject(error);
else resolve(contents);
});
});
}
var server = http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
fileContent(path.join(__dirname, 'page.html'), 'utf8')
.then(function(page) {
console.log(page);
res.end(page);
});
}).listen(8080);
Solution 3. Promise using async/await
var http = require('http');
var fs = require('fs');
var path = require('path');
var fileContent = function(path, format) {
return new Promise(function (resolve, reject) {
fs.readFile(path, format, function(error, contents) {
if (error) reject(error);
else resolve(contents);
});
});
}
var server = http.createServer(async function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
var page = await fileContent(path.join(__dirname, 'page.html'), 'utf8');
console.log(page);
res.end(page);
}).listen(8080);

nodeJS - make HTTPS request, sending JSON data

I would like to send an HTTPS POST from one nodeJS server to another. I have some JSON data I would like to send with this request (populated by a html form).
How can I do this? I am aware of https.request() but there does not seem to be an option to include JSON as a part of the query. From my research it seems possible with an HTTP request, but not an HTTPS request. How can I solve this?
const pug = require('pug');
var cloudinary = require('cloudinary');
var express = require('express');
var multer = require('multer');
var upload = multer({ dest: 'uploads/' });
var request = require('request');
var bodyParser = require('body-parser');
var options = {
hostname: 'ec2-54-202-139-197.us-west-2.compute.amazonaws.com',
port: 443,
path: '/',
method: 'GET'
};
var app = express();
var parser = bodyParser.raw();
app.use(parser);
app.set('view engine', 'pug');
app.get('/', upload.single('avatar'), function(req, res) {
return res.render('index.pug');
});
app.get('/makeRequest*', function(req, res) {
query = req['query'];
/*
Here, I would like to send the contents of the query variable as JSON to the server specified in options.
*/
});
You can send JSON data through a POST http request with the native https node module, as stated in the documentation
All options from http.request() are valid.
So, taking the http.request() example you can do the following:
var postData = querystring.stringify({
'msg' : 'Hello World!'
});
var options = {
hostname: 'www.google.com',
port: 80,
path: '/upload',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(postData)
}
};
var req = https.request(options, (res) => {
console.log(`STATUS: ${res.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
res.setEncoding('utf8');
res.on('data', (chunk) => {
console.log(`BODY: ${chunk}`);
});
res.on('end', () => {
console.log('No more data in response.');
});
});
req.on('error', (e) => {
console.log(`problem with request: ${e.message}`);
});
// write data to request body
req.write(postData);
req.end();
You should edit postData to your desired JSON object
I believe the below is what you want. Using the request library. See comments in the code for my recommendations.
...
var options = {
hostname: 'ec2-54-202-139-197.us-west-2.compute.amazonaws.com',
port: 443,
path: '/',
method: 'POST',
json: true
};
...
//making a post request and sending up your query is better then putting it in the query string
app.post('/makeRequest', function(req, res) {
var query = req.body['query'];
//NOTE, you cannot use a GET request to send JSON. You'll need to use a POST request.
//(you may need to make changes on your other servers)
options.body = { payload: query };
request(options, function(err, response, body) {
if (err) {
//Handle error
return;
}
if (response.statusCode == 200) {
console.log('contents received');
}
});
});
as matt mentioned you need to use request
to send JSON object not JSON.Stringify so that at the server you can receive it using:
app.post('/makeRequest', function(req, res) {
console.log (req.body.param1);
}
Use the following code:
var request = require("request");
request({
'url':"http://www.url.com",
method: "POST",
json: true,
body: {'param1':'any value'}
}, function (error, resp, body) {
console.log ("check response.");
});

Node.js rendering either html or css, not both

Beginning my first node.js project and I'm finding that my code renders either the html with no styling, or the css code as plain text to the screen. I open the page and see the html code, change nothing but hit refresh, and I see the css, and it switches back and forth every time I hit refresh. Can anyone tell me how to get it to apply the styling? Thanks. My code:
http.createServer(function (req, res) {
if(req.method.toLowerCase() == 'get'){
fs.readFile('path\\to\\index.html', function (err, data) {
if (err) console.log(err);
res.writeHead(200, {'Content-Type': 'text/html'});
res.write(data);
//res.end();
});
}
if(req.method.toLowerCase() == 'get'){
fs.readFile('path\\to\\mystyle.css', function (err, data1) {
if (err) console.log(err);
res.writeHead(200, {'Content-Type': 'text/css'});
res.write(data1);
//res.end();
});
}
}).listen(4000, '127.0.0.1');
console.log('Server running at http://127.0.0.1:4000/');
The reason I have the 'res.end()'s commented out is that when I left either or both of them in, I got a 'write after end' error. But I presume my problem is somewhere in that?
Edit: Just to add, I get the same problem if I remove both IF statements. If I enclose both readFiles within the same IF statement, I get the 'write after end'.
This is what worked in the end:
var http = require('http');
var fs = require('fs');
var formidable = require("formidable");
var util = require('util');
var url = require('url');
var html;
fs.readFile(__dirname+'\\index.html', function(err, data) {
if (err){
console.log(err);
response.writeHead(404, {'Content-Type': 'text/html'});
}
html = data;
});
var css;
fs.readFile(__dirname+'\\mystyle.css', function(err, data) {
if (err){
console.log(err);
response.writeHead(404, {'Content-Type': 'text/html'});
}
css = data;
});
var js;
fs.readFile(__dirname+'\\management.js', function(err, data) {
if (err){
console.log(err);
response.writeHead(404, {'Content-Type': 'text/html'});
}
js = data;
});
var server = http.createServer(function (request, response) {
switch (request.url) {
case "/mystyle.css" :
response.writeHead(200, {"Content-Type": "text/css"});
response.write(css);
break;
case "/management.js" :
response.writeHead(200, {"Content-Type": "text/javascript"});
response.write(js);
break;
default :
response.writeHead(200, {"Content-Type": "text/html"});
response.write(html);
};
response.end();
})
server.listen(4000);
console.log('server is listening at 4000');
You could easily put all the code inside the createServer function but the key is the switch.

Serving HTML file from Node server

Pretty much purely for pedagogical purposes, I'm serving both my front and back end data out of my one node server. Right now, I'm at the point where I've received my client request successfully, created some data based on said request, am able to console log it, etc. Everything is fine up to that point. My issue is that in the event that my data is only an html file, which is being read with the fs library, it will not render on the page when I attempt to serve it out in my res.end() or res.write(). I can see it's exactly what I want and expect when I console log it, but it just doesn't render in the browser. Any help would be appreciated. I've got it set up to where I'm handling my requests in an "if/else" wherein I only have the two scenarios of "/" (home), in which case I serve the html file, and anything else because the server really only needs to handle those two events. Thanks in advance.
Edit. This is what I have so far:
function responseHandler(req, res) {
res.writeHead(200, {"Content-Type": "text/html"});
if (req.url.match("fav")) {
res.end("");
return;
}
else if (req.url.match("/endpoint")) {
var input = req.url.match(/endpoint\/(.*)/)[1];
var output = endpoint.toHTML(decodeURI(input));
res.end(data);
console.log(input, req.url)
}
else {
fs.readFile("index.html", "utf8", function(err, data) {
console.log("data:" + data);
var input = req.url.match(/endpoint\/(.*)/)[1];
var output = endpoint.toHTML(decodeURI(input));
});
}
res.end();
}
I can see the data in the console which, in the last case, is just my HTML file. It just won't render in the page.
How did you attempted to serve the html with res.end() and res.write() ?
I just made a small test here, and this works:
app.js
var http = require('http');
var fs = require('fs');
var html = fs.readFileSync('hello-world.html');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(html);
}).listen(8000);
hello-world.html
<h3>Hello World</h3>
Edit: To match with your code, try this:
function responseHandler(req, res) {
res.writeHead(200, {"Content-Type": "text/html"});
if (req.url.match("fav")) {
res.end("");
return;
} else if (req.url.match("/endpoint")) {
var input = req.url.match(/endpoint\/(.*)/)[1];
var output = endpoint.toHTML(decodeURI(input));
console.log(input, req.url);
// we have no data variable in this scope
res.end("");
// I added a return statement in each step
// Just to be clear that we don't want to go if any
// condition have fit, since we cannot call res.end()
// more than once
return;
} else {
fs.readFile("index.html", "utf8", function(err, data) {
// error handling
if (err) return res.end(err);
// now we have the data
console.log("data:" + data);
res.end(data);
});
return;
}
}
Serving html in asynchronous way works something like that;
var fs = require('fs');
var http = require('http');
http.createServer(function(req, res){
res.writeHead(200, {'Content-Type': 'text/html'});
fs.readFile('index.html', function(err, data){
if(err){
return console.log(err);
}
res.end(data);
});
}).listen(8080);
console.log('Server is running on Port: 8080');

NodeJS: saving JSON to MongoDB

I am trying to get JSON from an API and store it into a MongoDB database.
Obviously, it doesn't work. My app seems to hang around the point where I try to save the data to the database. Please advise what to do.
Here's my code:
var express = require('express');
var router = express.Router();
var http = require('http');
var mongo = require('mongoskin');
var db = mongo.db("mongodb://localhost:27017/zak", {native_parser : true});
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
var site = 'http://www.vsechnyzakazky.cz/api/v1/zakazka/?format=json&limit=2';
function getData(cb) {
http.get(site, function(res) {
// explicitly treat incoming data as utf8 (avoids issues with multi-byte chars)
res.setEncoding('utf8');
// incrementally capture the incoming response body
var body = '';
res.on('data', function(d) {
body += d;
});
// do whatever we want with the response once it's done
res.on('end', function() {
try {
var parsed = JSON.parse(body);
} catch (err) {
console.error('Unable to parse response as JSON', err);
return cb(err);
}
// pass the relevant data back to the callback
cb(
parsed.objects
);
});
}).on('error', function(err) {
// handle errors with the request itself
console.error('Error with the request:', err.message);
cb(err);
});
}
function writeData (data, allGood){
// couple of visual checks if all looking good before writing to db
console.log('writing');
console.log(typeof data);
console.log(data);
db.collection('zakazky').save(data, function(error, record){
if (error) throw error;
console.log("data saved");
});
}
function allGood(){console.log('all done');}
getData(writeData);
// ---------------------
module.exports = router;
You are calling the save() instead of insert(). Change this part and it will work:
// this should call insert, not save
db.collection('zakazky').insert(data, function(error, record){
if (error) throw error;
console.log("data saved");
});