This code defines a httpRequest
function that makes HTTP requests using either the request
module (if available) or a custom implementation based on the http
and https
modules.
npm run import -- "https request"
var promisify
try {
promisify = require('util').promisify
} catch (e) {
if(!e.message.includes('Cannot find module')) {
throw e
}
}
if(!promisify) {
try {
promisify = require('bluebird').promisify
} catch (e) {
if(!e.message.includes('Cannot find module')) {
throw e
}
}
}
try {
var httpRequest = util.promisify(require('request'));
} catch (e) {
if(!e.message.includes('Cannot find module')) {
throw e
}
var http = require('http')
var https = require('https')
var url = require('url')
function httpRequest(params) {
var protocol = params.url.includes('http://') ? http : https
var location = url.parse(params.url)
var postData = querystring.stringify(params.data);
Object.assign(params, {
path: location.pathname,
host: location.hostname,
port: location.port || location.protocol === 'http' ? 80 : 443,
headers: Object.assign(params.headers || {}, {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(postData)
}, params.headers)
}, params)
return new Promise(function(resolve, reject) {
var req = protocol.request(params, function(res) {
// cumulate data
res.setEncoding('utf8');
res.body = [];
res.on('data', function(chunk) {
res.body.push(chunk);
});
// resolve on end
res.on('end', function() {
try {
res.body = res.body.join('');
} catch(e) {
reject(e);
}
resolve(res);
});
});
req.on('error', err => reject(err));
if (params.data) {
req.write(postData);
}
// IMPORTANT
req.end();
});
}
}
function request(...args) {
return httpRequest(...args)
.then(res => {
if(res.statusCode < 200 || res.statusCode >= 300) {
throw new Error('Error: ' + res.statusCode + ' - ' + JSON.stringify(res.body));
}
var isJson = (res.headers['content-type'] || '').match(/application\/json/ig);
var isPlain = (res.headers['content-type'] || '').match(/text\//ig);
if(isJson && typeof res.body !== 'undefined') {
try {
res.body = JSON.parse(res.body.toString('utf8'));
} catch (e) {}
}
if(isPlain && typeof res.body !== 'undefined') {
res.body = res.body.toString('utf8');
}
return res;
})
}
module.exports = {
request
}
const util = require('util');
const querystring = require('querystring');
const https = require('https');
const http = require('http');
const url = require('url');
// Try to use promisify from util if available
const promisify = util.promisify || (() => {
// If not, try to use promisify from bluebird if installed
try {
return require('bluebird').promisify;
} catch (error) {
// If bluebird is not installed, throw the error
if (!error.message.includes('Cannot find module')) {
throw error;
}
// If bluebird is not installed, do not throw any error
return util.promisify;
}
})();
// Promisify the request function
const request = promisify(require('request'));
// Function to create a promise-based version of request
function httpRequest(params) {
// Check if the promise is already created
if (params instanceof Promise) {
return params;
}
// Extract the protocol, location and data from the params
const protocol = params.url.includes('http://')? http : https;
const location = url.parse(params.url);
const postData = querystring.stringify(params.data);
// Create a new params object with the path, host, port and headers
const newParams = {
path: location.pathname,
host: location.hostname,
port: location.port || (location.protocol === 'http:'? 80 : 443),
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(postData)
}
};
// Merge the new params with the original params
Object.assign(newParams, params);
// Return a new promise
return new Promise((resolve, reject) => {
// Create a new request
const req = protocol.request(newParams, (res) => {
// Cumulate the data
res.setEncoding('utf8');
res.body = [];
res.on('data', (chunk) => {
res.body.push(chunk);
});
// Resolve the promise on end
res.on('end', () => {
try {
// Join the body chunks
res.body = res.body.join('');
} catch (error) {
// Reject the promise if an error occurs
reject(error);
}
// Resolve the promise with the response
resolve(res);
});
});
// Handle errors
req.on('error', (error) => reject(error));
// Write the data if it exists
if (params.data) {
req.write(postData);
}
// End the request
req.end();
});
}
// Function to handle the response
function handleResponse(res) {
// Check the status code and throw an error if it's not between 200 and 300
if (res.statusCode < 200 || res.statusCode >= 300) {
throw new Error(`Error: ${res.statusCode} - ${JSON.stringify(res.body)}`);
}
// Check if the response is JSON
const isJson = (res.headers['content-type'] || '').match(/application\/json/ig);
const isPlain = (res.headers['content-type'] || '').match(/text\//ig);
// Parse the body as JSON if it's a JSON response
if (isJson && typeof res.body!== 'undefined') {
try {
res.body = JSON.parse(res.body.toString('utf8'));
} catch (error) {
// Do nothing if an error occurs
}
}
// Set the body as a string if it's a plain text response
if (isPlain && typeof res.body!== 'undefined') {
res.body = res.body.toString('utf8');
}
// Return the response
return res;
}
// Export the request function
module.exports = {
request: (options) => {
// Call the request function with the options
return httpRequest(options).then(handleResponse);
}
};
This code snippet aims to provide a promisified httpRequest
function for making HTTP requests, handling potential errors gracefully and falling back to a custom implementation if the util.promisify
or bluebird
libraries are not available.
Here's a breakdown:
promisify
Detection and Fallback:
promisify
function from the util
module.util.promisify
is not found, it tries to get it from the bluebird
library.httpRequest
Function:
promisify
is successfully obtained, it attempts to promisify the request
module using util.promisify(require('request'))
.request
is not found, it falls back to a custom implementation using the http
and https
modules.Custom httpRequest
Implementation:
Promise
to handle asynchronous operations.In essence, this code provides a robust and flexible way to make HTTP requests in a Promise-based manner, gracefully handling potential dependency issues.