Node.js - multiple requests with cookies - javascript

I am building an app using Node.js. I am using the request package to make server-side GET requests. Specifically, I am making requests that use custom HTTP headers:
https://www.npmjs.com/package/request#custom-http-headers
The documentation shows how to make one request at a time. However, I need to make a request to two different API's. Does anyone have any idea how to do this? My current code for making one request:
var cookie = parseCookie.parseCookie(req.headers.cookie);
var cookieText = 'sid='+cookie;
var context;
function callback(error, response, body) {
var users = JSON.parse(body);
res.render('../views/users', {
context: users
});
}
var options = {
url: 'http://localhost:3000/api/admin/users/',
headers: {
host: 'localhost:3000',
connection: 'close',
cookie: cookieText
}
};
request(options, callback);
//need to make a request to another API.
As a side note, the reason I need to use custom HTTP headers is so I can include a cookie so my API can authenticate.

For flow control in nodejs, I would recommend you to use async
If you want to do in parallel without order of execution :
async.parallel([
function(callback) { request(apiCall1Options, callback); },
function(callback) { request(apiCall2Options, callback); }
], function(err, apiCallResults) { console.log(apiCallResults) })
If you need order, use async.waterfall.
Could be done as well by simply using plain callbacks, which I wouldnt recommend you using, or a promise library, like Q, or bluebird.

Related

Route that is executed within another route in Node.js is not being executed

Good Evening,
I have a function that contains a route that is a call to the Auth0 API and contains the updated data that was sent from the client. The function runs, but the app.patch() does not seem to run and I am not sure what I am missing.
function updateUser(val) {
app.patch(`https://${process.env.AUTH0_BASE_URL}/api/v2/users/${val.id}`,(res) => {
console.log(val);
res.header('Authorization: Bearer <insert token>)
res.json(val);
})
app.post('/updateuser', (req, ) => {
const val = req.body;
updateUser(val);
})
app.patch() does NOT send an outgoing request to another server. Instead, it registers a listener for incoming PATCH requests. It does not appear from your comments that that is what you want to do.
To send a PATCH request to another server, you need to use a library that is designed for sending http requests. There's a low level library built into the nodejs http module which you could use an http.request() to construct a PATCH request with, but it's generally a lot easier to use a higher level library such as any of them listed here.
My favorite in that list is the got() library, but many in that list are popular and used widely.
Using the got() library, you would send a PATCH request like this:
const got = require('got');
const options = {
headers: {Authorization: `Bearer ${someToken}`},
body: someData
};
const url = `https://${process.env.AUTH0_BASE_URL}/api/v2/users/${val.id}`;
got.patch(url, options).then(result => {
console.log(result);
}).catch(err => {
console.log(err);
});
Note: The PATCH request needs body data (the same that a POST needs body data)

How can you make an HTTP request to fetch the status.cgi json data from a Ubiquity AirMax or AirFibre radio with javascript?

My goal is to fetch the status data from a UBNT radio (https://www.ubnt.com/) using an HTTP request. The web interface url is formatted as http://192.168.0.120/status.cgi. Making the request requires a authentication cookie. Using the cookie copied from the existing web interface I am able to successfully retrieve the data.
This is my current code using the Meteor framework.
radioHost = "http://192.168.0.120";
HTTP.call("POST", radioHost + "/login.cgi",
{
headers: {
"Content-Type": "multipart/form-data"
},
data: {
username: "ubnt",
password: "ubnt"
}
}, (err, res) = > {
if(err) return console.log(err);
var cookie = res.headers["set-cookie"][0];
HTTP.call("GET", radioHost + "/status.cgi", {
headers: {
cookie
}
}, (err, res) = > {
if(err) return console.log("Error");
console.log(res);
})
})
The above code achieves both request successfully. However the server is responding to the first with a faulty token ("set-cookie" string). Using the cookie from the existing web framework the response is correct.
Here is a library written in Python that I believe does a similar thing. https://github.com/zmousm/ubnt-nagios-plugins
I believe my problem lies within the HTTP request and the web api not cooperating with the username and password.
Thanks in advance for any help.
A direct POST request to a url is not a recommended way. When you open a browser you just don't directly login. You fetch the page and then submit/login
Not simulating this behavior may impact certain sites depending on how the server works.
So if always want to look at the simulating like a real user/browser would do, make a GET request first and then the POST.
Also capture any cookies from the first GET request and then pass the same on to the next one

Using a oauth token in second request - NODEJS

Thanks for your help in advance.
I am trying to solve a problem that has bugged me pretty much for a few weeks now on and off (tried to solve it myself) and i am pretty stuck.
Basically i have a scenario where i am sending a data call to a identity server (Oauth 2.0) to retrieve a token that is then used in a API call.
To do this, i have setup two calls to the request module in NodeJS. The first call queries the server whilst the second call needs to use the token retrieved in the first to access the API i am accessing.
I cannot figure out how to get the variable from the first call (the token) to be accessible to the second request. I keep getting that it is undefined from the console.
This is the code i have tried so far. Relevant variable. Trying to take variable token through to request 2 as i need that token for the api call. I am running these requests in a function called dostuff.
var request = require('request');
var http = require('http');
var fs = require('fs');
var options = {
url: 'https://identitywebsite.com/connect/token',
headers: {'authorization' : 'basic <<KEY>>', 'Content-Type' : 'application/x-www-form-urlencoded'},
port: '443',
path: '/users',
method: 'POST',
body: 'grant_type=password&username=<<USERNAME>>&password=<<PASSWORD>>&scope=read+write'
var dostuff = function() {
request(options, function(error, response, body){
console.log("success");
Data = JSON.parse(body);
//console.log(xx);
global.token = data.access_token;
})
};
var options2 = {
url: 'https://apiwebsite.com',
headers: {'authorization' : 'Bearer ' + token, 'Content-Type' : 'application/json'},
port: '443',
path: '/users',
method: 'GET'
}
console.log(options2);
request(options2, function(error, response, apiresponse){
console.log("triggered");
console.log(" data success2");
apidata = JSON.parse(apiresponse);
console.log(apidata);
});
Well a few things you should do. One is use some promises. Also do your best to not use global variables.
Also you are missing a closing bracket on your first options.
Promises are really neat though, as you can do things like this.
do_something(options)
.then(function(my_data){
var options2 = {
url: 'https://apiwebsite.com',
headers: {'authorization' : 'Bearer ' + my_data, 'Content-Type' : 'application/json'},
port: '443',
path: '/users',
method: 'GET'
}
do_something_else(options2)
.then(function(my_other_data){
//do stuff with my_other_data
}
}
Use this library! It makes doing promises with requests really easy!
https://github.com/request/request-promise, you could also do this in bluebird which is my favorite of all the promise libraries, but it is slightly more complex.
Edit:
Since someone posted that this is off topic, which it isn't. I will go farther in depth of why this is not working the way you think it should. One of the reasons this is not working quite right is Node.JS is asynchronous.
What this means is your code is not waiting for your first request to finish before running your second request so you are not actually getting the token before your next request needs this.
One of the ways around this is to use promises like I said originally. There are plenty of libraries out there that force synchronicity. There is this library for example:
https://github.com/yortus/asyncawait
and many many more.
You could abstract this farther and call your first request from your second request as well to grab the API key and store it.

filter outgoing requests in node.js for logging

I am building an Express app which on certain requests has to make its own HTTP calls. I could use Superagent, request or node's own http.request.
Thing is, I need to log all of those server originating requests and their respective responses. Calling log.info before each and every of those seems silly.
How can you add a pre-filter for all outgoing HTTP calls, and ideally access both req and res?
NOTE: I am not interested in logging requests coming in to the server I am building, only in the requests that the server itself kicks off. Think of my server as a client to another black box server.
What you can do is patch http and https and proxy the request method. This way you can have a global handler that will catch the req & res objects.
var http = require('http');
var https = require('https');
var patch = function(object) {
var original = object.request;
// We proxy the request method
object.request = function(options, callback) {
// And we also proxy the callback to get res
var newCallback = function() {
var res = arguments[0];
// You can log res here
console.log("RES",res.statusCode);
callback.apply(this,arguments);
}
var req = original(options, newCallback);
// You can log your req object here.
console.log(req.method,req.path);
return req;
}
}
patch(http);
patch(https);
http.get("http://www.google.com/index.html", function(res) {
console.log("Got response");
}).on('error', function(e) {
console.log("Got error: " + e.message);
});
Edit: This might work if you use the request npm package as well, as it might just rely on the built-in node.js http.request method anyways.
What server are you going to use for you app?
I would definally bring up such functionality on to server level. Take a look how heroku router is doing it. You can track all of needed information using some of their addons: papertrail, or newrelic ( or use them separately for you app ).
https://papertrailapp.com/
http://newrelic.com/
I like out-of-box solutions in this case, no need extend your app logic for logging such information.
If you want to have your own solution, you can setup nginx to monitor request/response info.
http://nginx.com/resources/admin-guide/logging-and-monitoring/

Simple API Calls with Node.js and Express

I'm just getting started with Node, APIs, and web applications.
I understand the basic workings of Node.js and Express, but now I want to start making calls to other service's APIs and to do stuff with their data.
Can you outline basic HTTP requests and how to grab/parse the responses in Node? I'm also interested in adding specific headers to my request (initially I'm using the http://www.getharvest.com API to crunch my time sheet data).
P.S. This seems simple, but a lot of searching didn't turn up anything that answered my question. If this is dupe, let me know and I'll delete.
Thanks!
You cannot fetch stuff with Express, you should use Mikeal's request library for that specific purpose.
Installation: npm install request
The API for that library is very simple:
const request = require('request');
request('http://www.google.com', function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body) // Print the google web page.
}
})
Edit: You're better of using this library instead of the http default one because it has a much nicer API and some more advanced features (it even supports cookies).
UPDATE: request has been deprecated, but there are some nice alternatives still such as 'got' or 'superagent' (look them up on npm).
You can use the http client:
var http = require('http');
var client = http.createClient(3000, 'localhost');
var request = client.request('PUT', '/users/1');
request.write("stuff");
request.end();
request.on("response", function (response) {
// handle the response
});
Also, you can set headers as described in the api documentation:
client.request(method='GET', path, [request_headers])
Required install two package.
npm install ejs
npm install request
server.js
var request = require('request');
app.get('/users', function(req, res) {
request('https://jsonplaceholder.typicode.com/users', function(error, response, body) {
res.json(body)
});
});
index.ejs
$.ajax({
type: "GET",
url: 'http://127.0.0.1:3000/posts',
dataType: "json",
success: function(res) {
var res_data = JSON.parse(res);
console.log(res_data);
}
});
Output

Categories