node-fetch responding with 503 where request responding with 200 behind proxy - javascript

Below I have two http requests, one made with request and the other being made with isomorphic-fetch (node-fetch). For some reason the request with request works, however node-fetch is responding back with an error code 503. Is there anything I am missing from the fetch version?
const URL = require('url')
const fetch = require('isomorphic-fetch')
const HttpsProxyAgent = require('https-proxy-agent')
const request = require('request');
const url = process.env.URL
const proxy = process.env.PROXY
const requestPromise = function (url, options) {
if (/^\/\//.test(url)) {
url = 'https:' + url;
}
return new Promise(function(resolve, reject) {
return request.call(this, url, options, function (err, res, body) {
if (err) {
throw new Error(err);
}
res.ok = true;
res.json = function () {
return JSON.parse(res.body);
}
return resolve(res);
});
});
};
function getProxy (url) {
const parsedProxyURL = URL.parse(url);
parsedProxyURL.secureProxy = parsedProxyURL.protocol === 'https:';
return parsedProxyURL
}
requestPromise(url, {
agent:new HttpsProxyAgent(getProxy(proxy))
})
.then(console.log)
.catch(console.log)
fetch(url, {
agent:new HttpsProxyAgent(getProxy(proxy))
})
.then(console.log)
.catch(console.log)

The request module seems to be setting one header automatically, the host that fetch module is not. by making this change it works.
const URL = require('url')
const fetch = require('isomorphic-fetch')
const HttpsProxyAgent = require('https-proxy-agent')
const request = require('request')
function getProxy (url) {
const parsedProxyURL = URL.parse(url)
parsedProxyURL.secureProxy = parsedProxyURL.protocol === 'https:'
return parsedProxyURL
}
const url = process.env.URL
const proxy = process.env.PROXY
fetch(url, {
headers: {host: URL.parse(url).host},
agent: new HttpsProxyAgent(getProxy(proxy))
})
.then(res => res.json()).then(res => {
console.log(res)
})
.catch(console.log)

Related

Logout user on expired JWT token

I am trying to log out a user when the jwt token expires. I am trying to do it with axios interceptors, with the following code, but I get an infinite loop since it's asynchronous. Would anyone be able to tell how to go about it or if there is a better way? Thank you
axios.interceptors.request.use(async (req) => {
if (token) {
const userToken = jwt_decoder(token);
const isExpired = userToken.exp * 1000 < Date.now();
if (!isExpired) return req;
axios
.delete("users/sign_out")
.then((resp) => {
clearLocalStorage();
})
.catch((err) => {
clearLocalStorage();
});
}
return req;
});
Clearing the local storage before making the delete API call should stop the infinite loop. As it won't enter the if condition during the delete API call.
Try this.
axios.interceptors.request.use(async (req) => {
if (token) {
const userToken = jwt_decoder(token);
const isExpired = userToken.exp * 1000 < Date.now();
if (!isExpired) return req
clearLocalStorage();
axios
.delete("users/sign_out")
.then((resp) => {
clearLocalStorage();
})
.catch((err) => {
clearLocalStorage();
});
return req;
}
return req;
});
But as the comment on your question it is not advisable to carry out this check on the client. rather use the status code 401 (unauthorised)
axios.interceptors.request.use(async (req) => {
if (token) {
const userToken = jwt_decoder(token);
const isExpired = userToken.exp * 1000 < Date.now();
if (!isExpired) return req;
try {
const resp = await axios.delete("users/sign_out");
clearLocalStorage();
} catch(e) {
clearLocalStorage();
}
}
return req;
});

Request in lambda Node.JS doesn't work timeout [duplicate]

I hope everyone is well.
I have the following code that brings the value of a json:
const https = require('https');
var http = require("https");
var AWS = require('aws-sdk');
exports.handler = async (event, context, callback) => {
console.log('Event: ', JSON.stringify(event, null, 2));
const request = event.Records[0].cf.request;
const https = require('https');
const http_get = require('https');
var options = {
host: 'www.local.dev',
method: 'GET',
timeout: 2000,
path: '/list.json',
headers: {
'Accept': 'application/json'
}
};
const res = await new Promise(resolve => {
http_get.get(options, resolve);
});
let data = await new Promise((resolve, reject) => {
let data = '';
res.on('data', chunk => data += chunk);
res.on('error', err => reject(err));
res.on('end', () => resolve(data));
});
data = JSON.parse(data)
// CONTINUE FUNCTION
return request;
};
I would like to set a timeout, If the request does not return in 2 seconds, I continue the function, The function has other parts, so even if nothing comes from the json endpoint it can continue.
It has no dependency on the json return.
What is happening and that the timeout is not validated and the function is running indefinitely.
I need to use this http module from node.js, I can't use axios here.
To simulate the timeout I am using this app: httpstat.us/501?sleep=60000
Change this code
const res = await new Promise(resolve => {
http_get.get(options, resolve);
});
to this:
const res = http_get.get(options);
https.get returns a stream that is ready to use, and there is no reason to wrap that into a promise (where the syntax you are showing would be incorrect anyway).

Consuming external API from Hapi js server on startup not returning a promise

I am new to Hapi and I want to consume an API when the server starts up. I on start-up I am getting "Error: handler method did not return a value, a promise, or throw an error."
I came across this post and was trying to model my code after the answer supplied here, but it is not working, even though I am returning the promise from the fetch.
Here is my server.js.
"use strict";
var Hapi = require("#hapi/hapi");
var Request = require("request");
const Inert = require("#hapi/inert");
const Vision = require("#hapi/vision");
//Init server
const init = async () => {
const server = Hapi.server({
port: 3000,
host: "localhost",
routes: {
cors: true,
},
});
await server.register(Vision);
await server.register(Inert);
// await server.register(require("vision"));
server.route(require("./routes/getapis").getapis);
await server.start();
console.log(`Server is running on ${server.info.uri}`);
};
process.on("unhandledRejection", (err) => {
console.log(err);
process.exit(1);
});
init();
This is my getApis.js
const fetch = require("node-fetch");
const spendingApiUrl = `https://opendata.maryland.gov/resource/gja3-vy5r.json?$select=vendor_zip,sum(amount)&$where=vendor_zip between '20601' and '21930'&$group=vendor_zip&$order=sum_amount DESC`;
const numberOfTopZips = 3;
let results = [];
let marylandData = [];
exports.getApis = {
method: "GET",
path: "/getapis",
handler: (request, h) => {
return fetch(spendingApiUrl)
.then((response) => response.json())
.then((data) => {
marylandData = data;
console.log(marylandData);
//rateLimitedRequests(topZips(marylandData, numberOfTopZips));
})
.catch((err) => console.log(err));
},
};

Internal server error aws lambda function nodejs

I am trying out a demo with AWS lambda function using Axios and Cheerio, I am getting back response after calling the endpoint as {message: Internal Server Error}
exports.lambdaHandler = async (event, context) => {
try {
const axios = require('axios');
const cheerio = require('cheerio');
axios.get('https://www.kitco.com').then((response) => {
const html = response.data;
const $ = cheerio.load(html);
const ask = $('#AU-ask').text();
const bid = $('#AU-bid').text();
const resbid = bid.slice(0,7);
const resask = ask.slice(0,7);
const result = {
"ask": resask,
"bid": resbid
}
return result;
});
response = {
'statusCode': 200,
'body': result
}
} catch (err) {
console.log(err);
return err;
}
return response
};
result is clearly not in response scope, therefore this will result in a typical undefined error.
The solution would be to handle the logic inside axios.get callback, try this:
const axios = require('axios');
const cheerio = require('cheerio');
exports.lambdaHandler = (event, context) => {
axios.get('https://www.kitco.com')
.then((response) => {
const html = response.data;
const $ = cheerio.load(html);
const ask = $('#AU-ask').text();
const bid = $('#AU-bid').text();
const resbid = bid.slice(0, 7);
const resask = ask.slice(0, 7);
const result = {
statusCode: 200,
body: {
ask: resask,
bid: resbid
}
};
console.log(result);
})
.catch(err => {
console.log(err);
});
};
You can get error detail in monitor tab of Lambda console web. I guest you get back an error like response is undefined in return response line.
With your code, return response line will be execute immediately when you call the function, but response did not defined in the lambdaHandler scope.
I recommended that, don’t mix async/await syntax with Promise syntax (.then .catch), just use one of them, I suggest use async/await syntax.
The function will like:
exports.lambdaHandler = async (event, context) => {
try {
const axios = require('axios');
const cheerio = require('cheerio');
const response = await axios.get('https://www.kitco.com'); // wait until we get the response
const html = response.data;
const $ = cheerio.load(html);
const ask = $('#AU-ask').text();
const bid = $('#AU-bid').text();
const resbid = bid.slice(0, 7);
const resask = ask.slice(0, 7);
const result = {
"ask": resask,
"bid": resbid
}
return {
statusCode: 200,
body: JSON.stringify(result), // If you working with lambda-proxy-integrations, the `body` must be a string
}; // return to response the request
} catch (err) {
console.log(err);
return {
statusCode: 500, // Example, http status will be 500 when you got an exception
body: JSON.stringify({error: err}),
}
}
};

Multiple promise errors (promises must be constructed via new)

I am trying to create two asynch promises in my node app, to return all of the latestDeploymentDate(s) as they are fetched from an external API. I previously did this without promises, however I could not return all of the latestDeploymentDate(s) to the mapped array, because it was out of scope. Therefore I followed a JavaScript promises tutorial found on google, however I have been unsuccessful implementing it. Please find the code and the stack trace below:
const express = require('express')();
const request = require('request');
const moment = require('moment');
const ta = require('time-ago')();
var promise = require('promise')()
const webApplications = require('./account.json');
var newArr = new Array();
express.listen(3001, function() {
console.log('Server is listening...');
express.get('/data', function(req, res) {
res.json(webApplications.map((item, latestDeploymentDate) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Headers', true);
// return 'foo';
const newRelicRequest = {
url: `https://XXX`,
headers: {
'X-Api-Key': 'XXX'
}
}
const gitlabRequest = {
url: `XXX`,
headers: {
'PRIVATE-TOKEN': 'XXX'
}
}
var promise = new Promise(function(resolve, reject) {
request(newRelicRequest,(err, resp, body) => {
const data = JSON.parse(body);
const latestDeployment = data.deployments[0];
latestDeploymentDate = new Date(latestDeployment.timestamp);
console.log(new Date(latestDeployment.timestamp));
resolve(body);
});
var secondaryPromise = new Promise(function(resolve, reject) {
request(gitlabRequest, (err, resp, body) => {
const gitlabData = JSON.parse(body);
const currentTag = latestDeployment.description;
var currentIndex;
console.log(`${item.appName}` + ' ');
console.log(`Last deployed: ${latestDeployment.description}
on ${moment(latestDeploymentDate).format('YYYY-MM-DD')}`);
gitlabData.find((item, index) => {
currentIndex = index;
return item.name == currentTag
});
if (currentIndex > 3) {
console.log(`This ${currentIndex} was released ${ta.ago(latestDeploymentDate)}`);
resolve(latestDeploymentDate);
} else {
${ta.ago(latestDeploymentDate)}`);
console.log(`This ${currentIndex} was released ${ta.ago(latestDeploymentDate)}`);
resolve(latestDeploymentDate);
}
})
})
promise.then(function(result){
console.log(result)
})
});
}));
});
})
When you want to execute one promise after the other in a predictable order, you want to chain them:
promise()
|-----------------|
secondarypromise(promiseResult)
|------------------|
finalHandler(secondayPromiseResult)
|------------------|
In your code you can do this like so:
promise()
.then(secondaryPromise)
.then(finalHandler);
Note: I see that you are using request which is doesn't support Promises. May I recommend request-promise - that way you only need one library for your API calls. request-promise is just like request but it implements everything based on the Promises API.

Categories

Resources