OK, I must be dense since I cannot find anywhere how to get the error status codes when using Node.JS http.get or http.request.
My code:
var deferred = $q.defer();
var req = https.get(options, function(response) {
var str = '';
response.on('data', function(chunk) {
str += chunk;
});
response.on('end', function() {
console.log("[evfService] Got user info: " + str);
deferred.resolve(str);
});
});
req.on('error', function(e) {
deferred.reject(e);
});
In that "req.on" bit, what I want is the http status code (i.e. 401, 403, etc.). What I get is a semi-useless error object that does not give me the code or any reference to the response object.
I have tried intercepting in the function(response) callback, but when there is a 404, it never gets called.
Thanks!
Your callback gets called regardless of the response status code from the server, so within your callback, check response.statusCode. That is, a 4xx status code isn't an error at the level you're working at; the server responded, it's just that the server responded by saying the resource wasn't available (etc.)
This is in the documentation but characteristically vague. Here's the example they give, with a comment pointing to the relevant bit:
var https = require('https');
https.get('https://encrypted.google.com/', function(res) {
console.log("statusCode: ", res.statusCode); // <======= Here's the status code
console.log("headers: ", res.headers);
res.on('data', function(d) {
process.stdout.write(d);
});
}).on('error', function(e) {
console.error(e);
});
If you try that with (say) an unknown resource, you'll see statusCode: 404.
So for what you're doing, you may want something like this:
var deferred = $q.defer();
var req = https.get(options, function (response) {
var str = "";
if (response.statusCode < 200 || response.statusCode > 299) { // (I don"t know if the 3xx responses come here, if so you"ll want to handle them appropriately
response.on("data", function() { } ); // ¹
deferred.reject(/*...with appropriate information, including statusCode if you like...*/);
}
else {
response.on("data", function (chunk) {
str += chunk;
});
response.on("end", function () {
console.log("[evfService] Got user info: " + str);
deferred.resolve(str);
});
}
});
req.on("error", function (e) {
deferred.reject(/*...with appropriate information, but status code is irrelevant [there isn"t one]...*/);
});
¹ The empty data event handler in the branch handling non-OK status codes is there because of this note in the documentation:
...if a 'response' event handler is added, then the data from the response object must be consumed, either by calling response.read() whenever there is a 'readable' event, or by adding a 'data' handler, or by calling the .resume() method. Until the data is consumed, the 'end' event will not fire. Also, until the data is read it will consume memory that can eventually lead to a 'process out of memory' error.
Since we're passing a function to https.get, we're hooking the 'response' event, which suggests we need to do one of those things (in this case, I've added a do-nothing data handler). Thanks to Nicolas2bert for pointing that out!.
An error code 400 response is not considered an error by node.js.
Try response.statusCode in this:
request.on('response', function (response) {});
Here's a very small example how to get the error code. Just change the https to http and create an error:
var https = require('https')
var username = "monajalal3"
var request = https.get("https://teamtreehouse.com/" + username +".json", function (response) {
console.log(response.statusCode);
});
request.on("error", function (error) {
console.error(error.status);
});
Related
I am making a GET call with the following URL
https://auth.ebay.com/oauth2/authorize?client_id=CLIENT_ID&response_type=code&redirect_uri=REDIRECT_URI&scope=https://api.ebay.com/oauth/api_scope
This URL will redirect me to a "success.php" website from my server. With that redirection, it adds in params to the URL. For example: https://www.example.com/success.php?code=12345.
I need to get that code param from this redirection. How can I do that?
I tried to do a basic .get() call, but it doesnt seem to work..
https.get(url, (resp) => {
let data = '';
// A chunk of data has been received.
resp.on('data', (chunk) => {
data += chunk;
});
// The whole response has been received. Print out the result.
resp.on('end', () => {
console.log(JSON.parse(data).explanation);
});
}).on("error", (err) => {
console.log("Error: " + err.message);
});
I have tried other ways that I thought would work from research on here, like waiting for the redirect, etc. Nothing seems to work.
It is a query param ( seems to me you are working with an oAuth flow, reading about how these flows work would also help you work out an approach to this)
So I would capture it the following way
app.get('/callback', function (req, res) {
var code = req.query.code || null;
console.log(code);
}
where /callback is the URL you are redirected to and where you can capture the code to request the authorization token
Based on the code you already have it seems you might want the following.
var https = require('https');
var url = 'https://auth.ebay.com/oauth2/authorize?client_id=CLIENT_ID&response_type=code&redirect_uri=REDIRECT_URI&scope=https://api.ebay.com/oauth/api_scope';
https.get(url, (resp) => {
var location = new URL(resp.headers.location);
var code = location.searchParams.get('code');
console.log(code);
}).on("error", (err) => {
console.log("Error: " + err.message);
});
My answer assumes you are writing the code that is making the request while #Jordi Riera assumes you are writing code to process the request. Might you tell us which it is?
I'm fairly new to Node and Javascript and I'm struggling with my first Node module. What I'm trying to do is export functions for specific API calls and I'd like to reuse my https.request function rather than duplicating the code in each function. For some reason I'm failing to wrap my head around how to pass the data back to my original function. Here's an abbreviated version - the listStuff function would be one of many to handle various api request actions.
'use strict';
const https = require('https');
const _ = require('underscore');
const hostStr = 'api.server.net';
function listStuff(){
var pathStr = '/release/api/stuff';
_apiCall(pathStr);
//Would like to handle the https response data here
};
function _apiCall(pathStr){
var options = {
host: hostStr,
path: pathStr
};
var req = https.get(options, function(res) {
console.log("statusCode: ", res.statusCode);
console.log("headers: ", res.headers);
var responseString = '';
res.on('data', function(d){
responseString += d;
});
res.on('end', function(){
var responseObject = JSON.parse(responseString);
});
});
req.end();
req.on('error', function(e){
console.log(e);
});
};
module.exports = {
listStuff: listStuff
};
Hope this helps. Register a callback in the apiCall function, and then check the callback params for error handling. Then, just make sure you return the callback when you want to end the function call (either in the on end or on error processing).
function listStuff(){
var pathStr = '/release/api/stuff';
_apiCall(pathStr, function(err, data) {
if (err) // handle err
//handle data.
});
};
function _apiCall(pathStr, callback){
var options = {
host: hostStr,
path: pathStr
};
var req = https.get(options, function(res) {
console.log("statusCode: ", res.statusCode);
console.log("headers: ", res.headers);
var responseString = '';
res.on('data', function(d){
responseString += d;
});
res.on('end', function(){
var responseObject = JSON.parse(responseString);
return callback(null, responseObject);
});
});
req.end();
req.on('error', function(e){
console.log(e);
return callback(e);
});
};
A slightly different approach using Promise objects. Note I looked into this as a learning exercise and hope it helps. I have not written all the code for you and the debugging is all yours!
Firstly make _apiCall returns a promise object.
function listStuff()
{
var pathStr = '/release/api/stuff';
var promise = _apiCall(pathStr);
promise.then( function( responceObject){
// handle response object data
});
promise.catch( function( error){
console.log( error.message); // report error
});
}
Next step is to make _apiCall return a promise object for the HTTPS request it will initiate inside the executor of promise creation.
function _apiCall(pathStr)
{ var options = {
host: hostStr,
path: pathStr
};
function beginGet( worked, failed)
{
// see below
}
return new Promise( beginGet);
}
Lastly write beginGet to initiate and call back success or fail functions depending on the outcome of the get request.
function beginGet( worked, failed)
{ var req;
var responseObj;
function getCallBack( res)
{ // all your get request handling code
// on error call failed( error)
// on sucessful completion, call worked(responseObj)
}
req = https.get(options, getCallBack);
}
Also please check with https.get documentation - I think it calls req.end() for you. All the other errors are mine :-)
Problem i am solving:
Write an HTTP server that receives only POST requests and converts incoming POST body characters to upper-case and returns it to the client.
Your server should listen on the port provided by the first argument to your program.
My Solution
var http = require('http');
var map = require('through2-map')
http.createServer(function(request,response){
if (request.method == 'POST'){
request.pipe(map(function (chunk) {
return chunk.toString().toUpperCase();
})).pipe(response);
}
}).listen(process.argv[2]);
Can i implement is without using through2-map ?
My crippling solution which doesn't work:
request.on('data',function(data){
body += data.toString();
console.log(body);
});
request.pipe(body.toUpperCase()).pipe(response);
Can i do the real hard way ?
In the 2nd snippet, body.toUpperCase() will act immediately before any of the 'data' events have actually occurred. The call to .on() only adds the event handler so it will be called, but doesn't yet call it.
You can use the 'end' event, along with 'data', to wait for all data chunks to be received, ready to be uppercased:
request.on('data', function (data) {
body += data.toString();
});
request.on('end', function () {
response.end(body.toUpperCase());
});
Note: Be sure that body is being declared and assigned an initial value:
var body = '';
response.on('data', ...);
// ...
I am making a REST API call from my php and Node.js application to a particular URL provided by the client which returns a Json object. It works fine from with the PHP. However, I am unable to receive data from my node application? What might be the possible reason can someone help me ?
Note: I have pasted a dummy REST URI for security reasons
It works fine with PHP infact i get the json formatted data in like couple of seconds.
$response =
file_get_contents('http://xyz.net/v2_resmgr/providers/pools'); echo
$response;
I try the same url using node.js i get a TimeOut error. I also tried setting the timeout but it would still not work.
var job = new CronJob({
cronTime: '0 */3 * * * *',
onTick: function () {
url= "http://xyznet/v2_resmgr/providers/pools";
var request = http.get(url, function (response) {
var buffer = "",
data,
route;
response.on("data", function (chunk) {
buffer += chunk;
});
response.on("end", function (err) {
console.log(buffer);
});
request.setTimeout( 200000, function( ) {
// handle timeout here
console.log("Time Out call to the Rest API");
});
});
},
start: true
});
job.start();
I don't know if this is the answer you are looking for, but life gets easier when you use the 'request' package (https://www.npmjs.org/package/request)
Here is what the code would look like using the request module:
var request = require('request');
request('http://xyznet/v2_resmgr/providers/pools', function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body) // Print the body of the response.
}
})
Update: I coded something a little closer to your post. The code below does not use the "request" module and it contacts the server every 3 seconds.
setInterval(function () {
http.get('http://echo.jsontest.com/key/value', function (response) {
var responseBody = '';
response.on('data', function (chunk) {
responseBody += chunk;
});
response.on('end', function () {
console.log(responseBody);
var object = JSON.parse(responseBody)
});
});
}, 3000);
I'm trying to make a request to here, if you click on the link you should see a JSON response (as expected). I've, tried https and http, it doesnt matter (at least I don't think so).
Anyways the problem when I try to get a response from the command line, I get non UTF-8 characters like �������B��������E��9 as a response, even when I specify utf-8 encoding. Ive tried the npm module request and doing node http/https requests.
All i need is to just return a JSON response.
I've also tried JSON.parse() but to no avail.
Here's the code I've tried
var request = require("request")
var url = endpoint;
request({
url: url,
json: true
}, function (error, response, body) {
if (!error && response.statusCode === 200) {
console.log(body); // Print the json response
}
})
and the basic http request
var endpoint = 'http://api.stackexchange.com/2.1/search/advanced?order=desc&sort=relevance&q=jsonp&site=stackoverflow';
var req = http.request(endpoint, function(res) {
res.setEncoding('utf8');
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
req.write('data\n');
req.write('data\n');
req.end();
Stackoverflow servers are misconfigured, so they return gzip-encoded body even though you didn't ask for it.
Looks like you have to gunzip your response after receiving it.