I have a simple http.get request to external api.
How can I access id and name variables from another function? Thanks!
app.use(function *(next){
var name = '';
var id = '';
var options = {
host: 'www.website.com',
path: '/json/somedata',
metohd: 'GET'
};
http.get(options, function(res) {
var body = '';
res.on('data', function(chunk) {
body+=chunk;
console.log(body);
})
res.on('end', function() {
var parsed = JSON.parse(body);
id = parsed.id;
name = parsed.name;
})
})
});
I guess you are using the npm module express, with the syntax you have there.
Your answer depends on where you are looking to use id and name. If you are trying to use it in a route or middleware after this one a common way to solve that problem is to attach the properties (in this case name and id) to the request. Remember to call next after you are finished otherwise express will not know you have finished all your processing
I've given a quick example below:
app.use(function (req, res, next){
var options = {
host: 'www.website.com',
path: '/json/somedata',
method: 'GET'
};
http.get(options, function(getResponse) {
var body = '';
getResponse.on('data', function(chunk) {
body+=chunk;
console.log(body);
})
getResponse.on('end', function() {
var parsed = JSON.parse(body);
req.id = parsed.id;
req.name = parsed.name;
next();
})
})
});
Related
Im following a article about http requests to nasa's pic of the day. I'm trying to display the JSON object in browser from my server. But all Node.js' examples outputs the api results to a server's console. is it possible to have my server save/forward the response to the browser? I'd like to understand the native http module before relying on any dependencies. Also I'm not sure if it makes a difference but I'm using express to create my server. anything will help even a high level explanation because I'm so confused.
const https = require('https');
app.get('/', (req, res) => {
var url = 'https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY';
var nasa_obj
var request = https.get(url, function (resp) {
var body = '';
resp.on('data', function (chunk) {
body += chunk;
});
resp.on('end', function () {
nasa_obj = JSON.parse(body);
console.log("Got a response: ", nasa_obj);
res.send(nasa_obj)
});
}).on('error', function (e) {
console.log("Got an error: ", e);
});
request.end()
})
UPDATED: CODE IS CORRECT
You only want to send the response once it has been returned to you:
const https = require('https');
app.get('/', (req, res, next) => {
var url = 'https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY';
var nasa_obj
var request = https.get(url, function (response) {
var body = '';
response.on('data', function (chunk) {
body += chunk;
});
response.on('end', function () {
console.log("Got a response: ", body);
res.send(body);
});
}).on('error', function (e) {
console.log("Got an error: ", e);
next(e); // Pass error to error handling middleware
});
request.end()
})
Also make sure you are properly handling errors. Either send back a response to the browser to, as the code above is doing, pass it on to error handling middleware.
I want to do a very simple task, yet I am stuck!
The scenario is like this:
After a get request to my api, I want to http.get from some external site, and then send back the response from this external site to the original api request.
Obviously, the calls are asychronous so the string loremParagraph, doesn't load correctly before sending it back to the api.
Also I get the error: Error: Can't set headers after they are sent.
Here is my code:
module.exports = function(app, express) {
var myLoremRouter = express.Router();
var loremParagraph = '';
//HTTP GET accessed at localhost:8081/mylorem
myLoremRouter.get('/', function(req, res) {
// Fetch one paragpraphlorem ipsum text from http://www.faux-texte.com/text-random-1.htm
http.get("http://www.faux-texte.com/text-random-1.html", function(resp) {
resp.on('data', function(chunk) {
// console.log('BODY: ' + chunk);
var $ = cheerio.load(chunk);
loremParagraph = $('div.Texte').text();
console.log(loremParagraph);
// console.log(resp.status);
});
})
// If any error has occured, log error to console
.on('error', function(e) {
console.log("Got error: " + e.message);
});
//Finally send the result back to the api call
res.json({ message: loremParagraph });
});
return myLoremRouter;
};
Try this. Here chunks are added till we are ready to use the complete data.
https://stackoverflow.com/a/21953201/6219247
myLoremRouter.get('/', function(req, res) {
var body = '';
http.get({
host: 'www.faux-texte.com',
port: 80,
path: '/text-random-1.html'
}, function(resp) {
resp.on('data', function(chunk) {
body += chunk;
});
resp.on('end', function(chunk) {
var $ = cheerio.load(body);
loremParagraph = $('div.Texte').text();
res.json({ message: loremParagraph });
});
})
.on('error', function(e) {
// handle/send error
res.send(/*...*/);
});
});
I'm testing fake HTTP requests on Node. But I get the same result (501) on the headers defining GET, POST methods or "FOO". I don't understand the output. Can someone give me a hint? The code:
var http = require('http');
var fs = require('fs');
var options = {
method: "FOO" //or GET
, uri: 'https://www.google.com'
};
var callback = function(response){
var exportJson= JSON.stringify(response.headers);
var arrayData =[];
response.on('data', function(data) {
arrayData += data;
});
response.on('end', function() {
console.log('THE DATA IS ' + arrayData);
});
fs.appendFile("input.txt", exportJson, function(err) {
if(err) {
return console.log(err);
}
});
}
var req = http.request(options, callback);
function test(){
for (var prop in options.method) {
//console.log(`options.method${prop} = ${options.method[prop]}`);
//console.log(req);
req;
}
}
test();
req.end();
"GET" or "FOO" methods the console says:
<h2>HTTP ERROR 500.19 - Internal Server Error</h2>
The options object has no uri key, you should use hostname.
Also, do not specify the protocol inside the host, use the key protocol.
Your object should be:
const options = {
hostname: 'www.google.com',
protocol: 'https:',
}
Remember that to use https you need to include the right module:
const https = require('https');
So I have a route and I have some ugly code in the route that I'd like to make a middleware. The only problem is that Express's documentation isn't clear and my code just 404s.
How can I accomplish this?
Route:
router.get('/product/:slug', function(req, res) {
//route params
var slug = req.params.slug;
var productResp; //scope up api response to pass to render()
console.log(slug);
//api call
Prismic.api("https://prismic.io/api").then(function(api) {
return api.getByUID('product' , slug);
}).then(function(response) {
app.use(markedHtml)
})
.catch(function(error) {
res.render('404');
})
});
Function:
var markedHtml = function(req, res, next) {
var md_col_1 = response.data["product.markdown-col-one"].value[0].text;
var md_col_1_1 = response.data["product.markdown-col-one"].value[1].text;
var md_col_2 = response.data["product.markdown-col-two"].value[0].text;
var md_col_2_1 = response.data["product.markdown-col-two"].value[1].text;
var md_col_3 = response.data["product.markdown-col-three"].value[0].text;
var md_col_3_1 = response.data["product.markdown-col-three"].value[1].text;
var html_col_1 = marked(md_col_1);
var html_col_1_1 = marked(md_col_1_1);
var html_col_2 = marked(md_col_2);
var html_col_2_1 = marked(md_col_2_1);
var html_col_3 = marked(md_col_3);
var html_col_3_1 = marked(md_col_3_1);
res.render('product-template', {
product: response,
md_one: html_col_1,
md_one_1: html_col_1_1,
md_two: html_col_2,
md_two_1: html_col_2_1,
md_three: html_col_3,
md_three_1: html_col_3_1,
})
next();
}
In your root app.js, you should see all of the middleware your app is using. These middleware are matched sequentially. If they do not include the route argument, they will naturally be applied to all requests. Your routes are among them, and they look something like this: app.use('/', routes);.
Underneath your routes in app.js, declare a new one:
const markedHtml = require('./middleware/markedHtml');
app.use('/product/:slug', markedHtml);
In ./middleware/marketHtml.js, your method will appear like so, without the next call:
const markedHtml = function(req, res, next) {
// Do stuff with req.apiResponse here.
...
res.render('product-template', {
...
});
}
module.exports = markedHtml;
Your original route will look like this:
router.get('/product/:slug', function(req, res, next) {
//route params
var slug = req.params.slug;
var productResp; //scope up api response to pass to render()
console.log(slug);
//api call
Prismic.api("https://prismic.io/api").then(function(api) {
return api.getByUID('product' , slug);
}).then(function(response) {
req.apiResponse = response;
next();
})
.catch(function(error) {
res.render('404');
});
});
Essentially, your original route will receive the client request, do the API calls etc, then (pun!) run into the next(); invocation. That cues express to execute the next applicable middleware, which happens to be markedHtml, from where the view render method will be invoked.
Let me know if anything was unclear or requires additional explanation.
Additional documentation can be found here: http://expressjs.com/en/4x/api.html#app.use
I'm new in Node.js, I have a problem.
I would like to save data from JSON object which I have downloaded from github API.
var http = require("http");
var express = require('express');
var app = express();
var github = require('octonode');
var client = github.client();
app.set('port', process.env.PORT || 8000);
var server = app.listen(app.get('port'), function() {
console.log('Express server listening on port ' + server.address().port);
});
app.get('/getUsers', function (req, response) {
response.writeHead(200, {'Content-Type': 'text/json'});
var result;
client.get('/users/angular/repos', {}, function (err, status, body, headers) {
result = response.write(JSON.stringify(body));
console.log(result); //JSON object
return result;
});
console.log(result); //undefined
});
How can I save an data from object to single variable?
(I want to then transform it to an Array and take some useful data).
You will not get result outside of the asynchronous call as it is not yet defined. To get this value either call a method inside the callback of query or use async module and pass it.
app.get('/getUsers', function (req, response) {
response.writeHead(200, {'Content-Type': 'text/json'});
var result;
client.get('/users/angular/repos', {}, function (err, status, body, headers) {
result = response.write(JSON.stringify(body));
console.log(result); //JSON object
doSomeOperationOnResult(result)
});
});
function doSomeOperationOnResult(result){
//Your operating code
}