Reputation: 15318
this is a difficult question to ask because I am mystified, but let's see…
I am comparing Got with https.get, and have the following, bare simple code that works. Both Got and https.get return exactly the same result.
But when I use exactly the same code in my Fastify application, Got works as expected but https.get results in a 308.
Is there some way I can debug this code to see what is being sent out by https.get that is causing the remote server to respond with a 308 instead of 200?
import got from 'got';
import https from 'https';
const withGot = async (uri) => {
try {
const json = JSON.parse((await got(uri)).body);
console.log(json);
}
catch (error) {
console.error(error);
}
}
const withHttps = async (uri) => {
try {
const json = await getRequest(uri);
console.log(json);
}
catch (error) {
console.error(error);
}
}
const getRequest = async (uri) => {
return new Promise((resolve) => {
https.get(uri, (res) => {
const { statusCode } = res;
const contentType = res.headers['content-type'];
let error;
/**
* Any 2xx status code signals a successful response but
* here we're only checking for 200.
**/
if (statusCode !== 200) {
error = new Error(`ERROR\n${'-'.repeat(50)}\nRequest Failed.\nURI: ${uri}\nStatus Code: ${statusCode}`);
}
else if (!/^application\/json/.test(contentType)) {
error = new Error(`Invalid content-type.\nExpected application/json but received ${contentType}`);
}
if (error) {
console.error(error.message);
/**
* Consume response data to free up memory
**/
res.resume();
return;
}
res.setEncoding('utf8');
let rawData = '';
res.on('data', (chunk) => { rawData += chunk; });
res.on('end', () => {
try {
const parsedData = JSON.parse(rawData);
resolve(parsedData);
}
catch (e) {
console.error(e.message);
}
});
}).on('error', (e) => {
console.error(`Got error: ${e.message}`);
});
});
}
const uri = 'https://zenodo.org/api/records/?q=phylogeny';
withGot(uri);
withHttps(uri);
Upvotes: 1
Views: 740
Reputation: 15318
I figured out the reason for the problem (and the solution)… seems like when I use https.get
, I still have to pass the options with a port 443 (the default port for https
), otherwise, https
seems to knock on port 80 and then gets redirected to port 443 which results in the server sending back html which causes the JSON parser to croak. If I pass an options object like below, then it works. But, it is still weird that the standalone script works fine without the options, so I continue to be mystified even though I have found a solution.
const options = {
hostname: 'zenodo.org',
port: 443,
path: `/api/records/?${qs}`,
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
};
Upvotes: 1