Skip to content

Instantly share code, notes, and snippets.

@ternavsky
Created July 25, 2024 12:36
Show Gist options
  • Save ternavsky/41cb8c1cfc3f4cff31e911c26119f752 to your computer and use it in GitHub Desktop.
Save ternavsky/41cb8c1cfc3f4cff31e911c26119f752 to your computer and use it in GitHub Desktop.
deprecated request-promise rewritten to use native "fetch" function.
const FormData = require('form-data');
const https = require('https');
const zlib = require('zlib');
async function rp(options) {
try {
// Check if options is a string URL
if (typeof options === 'string') {
options = { uri: options };
}
const {
method = 'GET', // HTTP method
headers = {}, // Request headers
body, // Request body for POST, PUT, etc.
json, // JSON flag or JSON object
qs, // Query string parameters
form, // Form data object
auth, // Authentication object { user, username, pass, password, sendImmediately, bearer }
followAllRedirects = false, // Follow all redirects
resolveWithFullResponse = false, // Return full response (including headers)
simple = true, // Reject based on response status
timeout, // Request timeout
cert, // Client certificate
key, // Client private key
strictSSL = true, // Strict SSL certificate validation
transform, // Transform function for response
gzip = false, // Use gzip compression
} = options;
let url = new URL(options.uri || options.url);
// Append query string parameters
if (qs) {
Object.keys(qs).forEach(key => url.searchParams.append(key, qs[key]));
}
// Fetch options setup
const fetchOptions = {
method,
headers,
redirect: followAllRedirects ? 'follow' : 'manual',
};
if (auth) {
const { user, username, pass, password, sendImmediately = true, bearer } = auth;
if (bearer) {
fetchOptions.headers['Authorization'] = `Bearer ${bearer}`;
} else {
const authUser = user || username;
const authPass = pass || password;
if (authUser && authPass) {
const encodedAuth = Buffer.from(`${authUser}:${authPass}`).toString('base64');
fetchOptions.headers['Authorization'] = `Basic ${encodedAuth}`;
} else if (sendImmediately) {
throw new Error('Missing authentication credentials');
}
}
}
if (json) {
fetchOptions.headers['Content-Type'] = 'application/json';
if (body || (typeof json !== 'boolean')) {
fetchOptions.body = JSON.stringify(body || json);
}
} else if (body) {
fetchOptions.body = body;
}
if (form) {
const formData = new FormData();
Object.keys(form).forEach(key => formData.append(key, form[key]));
fetchOptions.body = formData;
}
const agentOptions = {};
if (cert) agentOptions.cert = cert;
if (key) agentOptions.key = key;
agentOptions.rejectUnauthorized = strictSSL;
const agent = new https.Agent(agentOptions);
fetchOptions.agent = agent;
if (gzip) {
fetchOptions.headers['Accept-Encoding'] = 'gzip, deflate';
}
const controller = new AbortController();
fetchOptions.signal = controller.signal;
let timeoutId;
if (timeout) {
timeoutId = setTimeout(() => controller.abort(), timeout);
}
const response = await fetch(url, fetchOptions);
let responseText;
if (gzip && response.headers.get('content-encoding') === 'gzip') {
const buffer = await response.arrayBuffer();
const decompressed = zlib.gunzipSync(Buffer.from(buffer));
responseText = decompressed.toString('utf-8');
} else {
responseText = await response.text();
}
// Handle JSON response
if (json && typeof json !== 'object') {
try {
responseText = JSON.parse(responseText);
} catch (error) {
clearTimeout(timeoutId);
throw new Error(`Failed to parse JSON response: ${responseText}`);
}
}
if (simple && !response.ok) {
clearTimeout(timeoutId);
throw responseText;
}
if (transform) {
responseText = transform(responseText, response);
}
clearTimeout(timeoutId);
return resolveWithFullResponse ? { ...response, body: responseText } : responseText;
} catch (error) {
if (error.name === 'AbortError') {
throw {
name: 'RequestError',
message: 'Error: ETIMEDOUT',
error: {
code: 'ETIMEDOUT',
connect: true,
message: 'ETIMEDOUT'
}
};
}
throw new Error(`Request failed: ${error.message}`);
}
}
module.exports = rp;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment