2022-10-21 16:52:45 +02:00
/* eslint-disable @typescript-eslint/no-explicit-any */
var __awaiter = ( this && this . __awaiter ) || function ( thisArg , _arguments , P , generator ) {
function adopt ( value ) { return value instanceof P ? value : new P ( function ( resolve ) { resolve ( value ); }); }
return new ( P || ( P = Promise ))( function ( resolve , reject ) {
function fulfilled ( value ) { try { step ( generator . next ( value )); } catch ( e ) { reject ( e ); } }
function rejected ( value ) { try { step ( generator [ "throw" ]( value )); } catch ( e ) { reject ( e ); } }
function step ( result ) { result . done ? resolve ( result . value ) : adopt ( result . value ). then ( fulfilled , rejected ); }
step (( generator = generator . apply ( thisArg , _arguments || [])). next ());
});
};
2026-01-30 13:31:20 +01:00
import * as http from 'http' ;
import * as https from 'https' ;
import * as pm from './proxy.js' ;
import * as tunnel from 'tunnel' ;
import { ProxyAgent } from 'undici' ;
export var HttpCodes ;
2022-10-21 16:52:45 +02:00
( function ( HttpCodes ) {
HttpCodes [ HttpCodes [ "OK" ] = 200 ] = "OK" ;
HttpCodes [ HttpCodes [ "MultipleChoices" ] = 300 ] = "MultipleChoices" ;
HttpCodes [ HttpCodes [ "MovedPermanently" ] = 301 ] = "MovedPermanently" ;
HttpCodes [ HttpCodes [ "ResourceMoved" ] = 302 ] = "ResourceMoved" ;
HttpCodes [ HttpCodes [ "SeeOther" ] = 303 ] = "SeeOther" ;
HttpCodes [ HttpCodes [ "NotModified" ] = 304 ] = "NotModified" ;
HttpCodes [ HttpCodes [ "UseProxy" ] = 305 ] = "UseProxy" ;
HttpCodes [ HttpCodes [ "SwitchProxy" ] = 306 ] = "SwitchProxy" ;
HttpCodes [ HttpCodes [ "TemporaryRedirect" ] = 307 ] = "TemporaryRedirect" ;
HttpCodes [ HttpCodes [ "PermanentRedirect" ] = 308 ] = "PermanentRedirect" ;
HttpCodes [ HttpCodes [ "BadRequest" ] = 400 ] = "BadRequest" ;
HttpCodes [ HttpCodes [ "Unauthorized" ] = 401 ] = "Unauthorized" ;
HttpCodes [ HttpCodes [ "PaymentRequired" ] = 402 ] = "PaymentRequired" ;
HttpCodes [ HttpCodes [ "Forbidden" ] = 403 ] = "Forbidden" ;
HttpCodes [ HttpCodes [ "NotFound" ] = 404 ] = "NotFound" ;
HttpCodes [ HttpCodes [ "MethodNotAllowed" ] = 405 ] = "MethodNotAllowed" ;
HttpCodes [ HttpCodes [ "NotAcceptable" ] = 406 ] = "NotAcceptable" ;
HttpCodes [ HttpCodes [ "ProxyAuthenticationRequired" ] = 407 ] = "ProxyAuthenticationRequired" ;
HttpCodes [ HttpCodes [ "RequestTimeout" ] = 408 ] = "RequestTimeout" ;
HttpCodes [ HttpCodes [ "Conflict" ] = 409 ] = "Conflict" ;
HttpCodes [ HttpCodes [ "Gone" ] = 410 ] = "Gone" ;
HttpCodes [ HttpCodes [ "TooManyRequests" ] = 429 ] = "TooManyRequests" ;
HttpCodes [ HttpCodes [ "InternalServerError" ] = 500 ] = "InternalServerError" ;
HttpCodes [ HttpCodes [ "NotImplemented" ] = 501 ] = "NotImplemented" ;
HttpCodes [ HttpCodes [ "BadGateway" ] = 502 ] = "BadGateway" ;
HttpCodes [ HttpCodes [ "ServiceUnavailable" ] = 503 ] = "ServiceUnavailable" ;
HttpCodes [ HttpCodes [ "GatewayTimeout" ] = 504 ] = "GatewayTimeout" ;
2026-01-30 13:31:20 +01:00
})( HttpCodes || ( HttpCodes = {}));
export var Headers ;
2022-10-21 16:52:45 +02:00
( function ( Headers ) {
Headers [ "Accept" ] = "accept" ;
Headers [ "ContentType" ] = "content-type" ;
2026-01-30 13:31:20 +01:00
})( Headers || ( Headers = {}));
export var MediaTypes ;
2022-10-21 16:52:45 +02:00
( function ( MediaTypes ) {
MediaTypes [ "ApplicationJson" ] = "application/json" ;
2026-01-30 13:31:20 +01:00
})( MediaTypes || ( MediaTypes = {}));
2022-10-21 16:52:45 +02:00
/**
* Returns the proxy URL, depending upon the supplied url and proxy environment variables.
* @param serverUrl The server URL where the request will be sent. For example, https://api.github.com
*/
2026-01-30 13:31:20 +01:00
export function getProxyUrl ( serverUrl ) {
2022-10-21 16:52:45 +02:00
const proxyUrl = pm . getProxyUrl ( new URL ( serverUrl ));
return proxyUrl ? proxyUrl . href : '' ;
}
const HttpRedirectCodes = [
HttpCodes . MovedPermanently ,
HttpCodes . ResourceMoved ,
HttpCodes . SeeOther ,
HttpCodes . TemporaryRedirect ,
HttpCodes . PermanentRedirect
];
const HttpResponseRetryCodes = [
HttpCodes . BadGateway ,
HttpCodes . ServiceUnavailable ,
HttpCodes . GatewayTimeout
];
const RetryableHttpVerbs = [ 'OPTIONS' , 'GET' , 'DELETE' , 'HEAD' ];
const ExponentialBackoffCeiling = 10 ;
const ExponentialBackoffTimeSlice = 5 ;
2026-01-30 13:31:20 +01:00
export class HttpClientError extends Error {
2022-10-21 16:52:45 +02:00
constructor ( message , statusCode ) {
super ( message );
this . name = 'HttpClientError' ;
this . statusCode = statusCode ;
Object . setPrototypeOf ( this , HttpClientError . prototype );
}
}
2026-01-30 13:31:20 +01:00
export class HttpClientResponse {
2022-10-21 16:52:45 +02:00
constructor ( message ) {
this . message = message ;
}
readBody () {
return __awaiter ( this , void 0 , void 0 , function * () {
return new Promise (( resolve ) => __awaiter ( this , void 0 , void 0 , function * () {
let output = Buffer . alloc ( 0 );
this . message . on ( 'data' , ( chunk ) => {
output = Buffer . concat ([ output , chunk ]);
});
this . message . on ( 'end' , () => {
resolve ( output . toString ());
});
}));
});
}
2025-06-13 19:44:16 +02:00
readBodyBuffer () {
return __awaiter ( this , void 0 , void 0 , function * () {
return new Promise (( resolve ) => __awaiter ( this , void 0 , void 0 , function * () {
const chunks = [];
this . message . on ( 'data' , ( chunk ) => {
chunks . push ( chunk );
});
this . message . on ( 'end' , () => {
resolve ( Buffer . concat ( chunks ));
});
}));
});
}
2022-10-21 16:52:45 +02:00
}
2026-01-30 13:31:20 +01:00
export function isHttps ( requestUrl ) {
2022-10-21 16:52:45 +02:00
const parsedUrl = new URL ( requestUrl );
return parsedUrl . protocol === 'https:' ;
}
2026-01-30 13:31:20 +01:00
export class HttpClient {
2022-10-21 16:52:45 +02:00
constructor ( userAgent , handlers , requestOptions ) {
this . _ignoreSslError = false ;
this . _allowRedirects = true ;
this . _allowRedirectDowngrade = false ;
this . _maxRedirects = 50 ;
this . _allowRetries = false ;
this . _maxRetries = 1 ;
this . _keepAlive = false ;
this . _disposed = false ;
2026-01-09 14:32:48 +01:00
this . userAgent = this . _getUserAgentWithOrchestrationId ( userAgent );
2022-10-21 16:52:45 +02:00
this . handlers = handlers || [];
this . requestOptions = requestOptions ;
if ( requestOptions ) {
if ( requestOptions . ignoreSslError != null ) {
this . _ignoreSslError = requestOptions . ignoreSslError ;
}
this . _socketTimeout = requestOptions . socketTimeout ;
if ( requestOptions . allowRedirects != null ) {
this . _allowRedirects = requestOptions . allowRedirects ;
}
if ( requestOptions . allowRedirectDowngrade != null ) {
this . _allowRedirectDowngrade = requestOptions . allowRedirectDowngrade ;
}
if ( requestOptions . maxRedirects != null ) {
this . _maxRedirects = Math . max ( requestOptions . maxRedirects , 0 );
}
if ( requestOptions . keepAlive != null ) {
this . _keepAlive = requestOptions . keepAlive ;
}
if ( requestOptions . allowRetries != null ) {
this . _allowRetries = requestOptions . allowRetries ;
}
if ( requestOptions . maxRetries != null ) {
this . _maxRetries = requestOptions . maxRetries ;
}
}
}
options ( requestUrl , additionalHeaders ) {
return __awaiter ( this , void 0 , void 0 , function * () {
return this . request ( 'OPTIONS' , requestUrl , null , additionalHeaders || {});
});
}
get ( requestUrl , additionalHeaders ) {
return __awaiter ( this , void 0 , void 0 , function * () {
return this . request ( 'GET' , requestUrl , null , additionalHeaders || {});
});
}
del ( requestUrl , additionalHeaders ) {
return __awaiter ( this , void 0 , void 0 , function * () {
return this . request ( 'DELETE' , requestUrl , null , additionalHeaders || {});
});
}
post ( requestUrl , data , additionalHeaders ) {
return __awaiter ( this , void 0 , void 0 , function * () {
return this . request ( 'POST' , requestUrl , data , additionalHeaders || {});
});
}
patch ( requestUrl , data , additionalHeaders ) {
return __awaiter ( this , void 0 , void 0 , function * () {
return this . request ( 'PATCH' , requestUrl , data , additionalHeaders || {});
});
}
put ( requestUrl , data , additionalHeaders ) {
return __awaiter ( this , void 0 , void 0 , function * () {
return this . request ( 'PUT' , requestUrl , data , additionalHeaders || {});
});
}
head ( requestUrl , additionalHeaders ) {
return __awaiter ( this , void 0 , void 0 , function * () {
return this . request ( 'HEAD' , requestUrl , null , additionalHeaders || {});
});
}
sendStream ( verb , requestUrl , stream , additionalHeaders ) {
return __awaiter ( this , void 0 , void 0 , function * () {
return this . request ( verb , requestUrl , stream , additionalHeaders );
});
}
/**
* Gets a typed object from an endpoint
* Be aware that not found returns a null. Other errors (4xx, 5xx) reject the promise
*/
2025-12-25 10:58:28 +01:00
getJson ( requestUrl_1 ) {
return __awaiter ( this , arguments , void 0 , function * ( requestUrl , additionalHeaders = {}) {
2022-10-21 16:52:45 +02:00
additionalHeaders [ Headers . Accept ] = this . _getExistingOrDefaultHeader ( additionalHeaders , Headers . Accept , MediaTypes . ApplicationJson );
const res = yield this . get ( requestUrl , additionalHeaders );
return this . _processResponse ( res , this . requestOptions );
});
}
2025-12-25 10:58:28 +01:00
postJson ( requestUrl_1 , obj_1 ) {
return __awaiter ( this , arguments , void 0 , function * ( requestUrl , obj , additionalHeaders = {}) {
2022-10-21 16:52:45 +02:00
const data = JSON . stringify ( obj , null , 2 );
additionalHeaders [ Headers . Accept ] = this . _getExistingOrDefaultHeader ( additionalHeaders , Headers . Accept , MediaTypes . ApplicationJson );
2025-12-25 10:58:28 +01:00
additionalHeaders [ Headers . ContentType ] =
this . _getExistingOrDefaultContentTypeHeader ( additionalHeaders , MediaTypes . ApplicationJson );
2022-10-21 16:52:45 +02:00
const res = yield this . post ( requestUrl , data , additionalHeaders );
return this . _processResponse ( res , this . requestOptions );
});
}
2025-12-25 10:58:28 +01:00
putJson ( requestUrl_1 , obj_1 ) {
return __awaiter ( this , arguments , void 0 , function * ( requestUrl , obj , additionalHeaders = {}) {
2022-10-21 16:52:45 +02:00
const data = JSON . stringify ( obj , null , 2 );
additionalHeaders [ Headers . Accept ] = this . _getExistingOrDefaultHeader ( additionalHeaders , Headers . Accept , MediaTypes . ApplicationJson );
2025-12-25 10:58:28 +01:00
additionalHeaders [ Headers . ContentType ] =
this . _getExistingOrDefaultContentTypeHeader ( additionalHeaders , MediaTypes . ApplicationJson );
2022-10-21 16:52:45 +02:00
const res = yield this . put ( requestUrl , data , additionalHeaders );
return this . _processResponse ( res , this . requestOptions );
});
}
2025-12-25 10:58:28 +01:00
patchJson ( requestUrl_1 , obj_1 ) {
return __awaiter ( this , arguments , void 0 , function * ( requestUrl , obj , additionalHeaders = {}) {
2022-10-21 16:52:45 +02:00
const data = JSON . stringify ( obj , null , 2 );
additionalHeaders [ Headers . Accept ] = this . _getExistingOrDefaultHeader ( additionalHeaders , Headers . Accept , MediaTypes . ApplicationJson );
2025-12-25 10:58:28 +01:00
additionalHeaders [ Headers . ContentType ] =
this . _getExistingOrDefaultContentTypeHeader ( additionalHeaders , MediaTypes . ApplicationJson );
2022-10-21 16:52:45 +02:00
const res = yield this . patch ( requestUrl , data , additionalHeaders );
return this . _processResponse ( res , this . requestOptions );
});
}
/**
* Makes a raw http request.
* All other methods such as get, post, patch, and request ultimately call this.
* Prefer get, del, post and patch
*/
request ( verb , requestUrl , data , headers ) {
return __awaiter ( this , void 0 , void 0 , function * () {
if ( this . _disposed ) {
throw new Error ( 'Client has already been disposed.' );
}
const parsedUrl = new URL ( requestUrl );
let info = this . _prepareRequest ( verb , parsedUrl , headers );
// Only perform retries on reads since writes may not be idempotent.
const maxTries = this . _allowRetries && RetryableHttpVerbs . includes ( verb )
? this . _maxRetries + 1
: 1 ;
let numTries = 0 ;
let response ;
do {
response = yield this . requestRaw ( info , data );
// Check if it's an authentication challenge
if ( response &&
response . message &&
response . message . statusCode === HttpCodes . Unauthorized ) {
let authenticationHandler ;
for ( const handler of this . handlers ) {
if ( handler . canHandleAuthentication ( response )) {
authenticationHandler = handler ;
break ;
}
}
if ( authenticationHandler ) {
return authenticationHandler . handleAuthentication ( this , info , data );
}
else {
// We have received an unauthorized response but have no handlers to handle it.
// Let the response return to the caller.
return response ;
}
}
let redirectsRemaining = this . _maxRedirects ;
while ( response . message . statusCode &&
HttpRedirectCodes . includes ( response . message . statusCode ) &&
this . _allowRedirects &&
redirectsRemaining > 0 ) {
const redirectUrl = response . message . headers [ 'location' ];
if ( ! redirectUrl ) {
// if there's no location to redirect to, we won't
break ;
}
const parsedRedirectUrl = new URL ( redirectUrl );
if ( parsedUrl . protocol === 'https:' &&
parsedUrl . protocol !== parsedRedirectUrl . protocol &&
! this . _allowRedirectDowngrade ) {
throw new Error ( 'Redirect from HTTPS to HTTP protocol. This downgrade is not allowed for security reasons. If you want to allow this behavior, set the allowRedirectDowngrade option to true.' );
}
// we need to finish reading the response before reassigning response
// which will leak the open socket.
yield response . readBody ();
// strip authorization header if redirected to a different hostname
if ( parsedRedirectUrl . hostname !== parsedUrl . hostname ) {
for ( const header in headers ) {
// header names are case insensitive
if ( header . toLowerCase () === 'authorization' ) {
delete headers [ header ];
}
}
}
// let's make the request with the new redirectUrl
info = this . _prepareRequest ( verb , parsedRedirectUrl , headers );
response = yield this . requestRaw ( info , data );
redirectsRemaining -- ;
}
if ( ! response . message . statusCode ||
! HttpResponseRetryCodes . includes ( response . message . statusCode )) {
// If not a retry code, return immediately instead of retrying
return response ;
}
numTries += 1 ;
if ( numTries < maxTries ) {
yield response . readBody ();
yield this . _performExponentialBackoff ( numTries );
}
} while ( numTries < maxTries );
return response ;
});
}
/**
* Needs to be called if keepAlive is set to true in request options.
*/
dispose () {
if ( this . _agent ) {
this . _agent . destroy ();
}
this . _disposed = true ;
}
/**
* Raw request.
* @param info
* @param data
*/
requestRaw ( info , data ) {
return __awaiter ( this , void 0 , void 0 , function * () {
return new Promise (( resolve , reject ) => {
function callbackForResult ( err , res ) {
if ( err ) {
reject ( err );
}
else if ( ! res ) {
// If `err` is not passed, then `res` must be passed.
reject ( new Error ( 'Unknown error' ));
}
else {
resolve ( res );
}
}
this . requestRawWithCallback ( info , data , callbackForResult );
});
});
}
/**
* Raw request with callback.
* @param info
* @param data
* @param onResult
*/
requestRawWithCallback ( info , data , onResult ) {
if ( typeof data === 'string' ) {
if ( ! info . options . headers ) {
info . options . headers = {};
}
info . options . headers [ 'Content-Length' ] = Buffer . byteLength ( data , 'utf8' );
}
let callbackCalled = false ;
function handleResult ( err , res ) {
if ( ! callbackCalled ) {
callbackCalled = true ;
onResult ( err , res );
}
}
const req = info . httpModule . request ( info . options , ( msg ) => {
const res = new HttpClientResponse ( msg );
handleResult ( undefined , res );
});
let socket ;
req . on ( 'socket' , sock => {
socket = sock ;
});
// If we ever get disconnected, we want the socket to timeout eventually
req . setTimeout ( this . _socketTimeout || 3 * 60000 , () => {
if ( socket ) {
socket . end ();
}
handleResult ( new Error ( `Request timeout: ${ info . options . path } ` ));
});
req . on ( 'error' , function ( err ) {
// err has statusCode property
// res should have headers
handleResult ( err );
});
if ( data && typeof data === 'string' ) {
req . write ( data , 'utf8' );
}
if ( data && typeof data !== 'string' ) {
data . on ( 'close' , function () {
req . end ();
});
data . pipe ( req );
}
else {
req . end ();
}
}
/**
* Gets an http agent. This function is useful when you need an http agent that handles
* routing through a proxy server - depending upon the url and proxy environment variables.
* @param serverUrl The server URL where the request will be sent. For example, https://api.github.com
*/
getAgent ( serverUrl ) {
const parsedUrl = new URL ( serverUrl );
return this . _getAgent ( parsedUrl );
}
2025-06-13 19:44:16 +02:00
getAgentDispatcher ( serverUrl ) {
const parsedUrl = new URL ( serverUrl );
const proxyUrl = pm . getProxyUrl ( parsedUrl );
const useProxy = proxyUrl && proxyUrl . hostname ;
if ( ! useProxy ) {
return ;
}
return this . _getProxyAgentDispatcher ( parsedUrl , proxyUrl );
}
2022-10-21 16:52:45 +02:00
_prepareRequest ( method , requestUrl , headers ) {
const info = {};
info . parsedUrl = requestUrl ;
const usingSsl = info . parsedUrl . protocol === 'https:' ;
info . httpModule = usingSsl ? https : http ;
const defaultPort = usingSsl ? 443 : 80 ;
info . options = {};
info . options . host = info . parsedUrl . hostname ;
info . options . port = info . parsedUrl . port
? parseInt ( info . parsedUrl . port )
: defaultPort ;
info . options . path =
( info . parsedUrl . pathname || '' ) + ( info . parsedUrl . search || '' );
info . options . method = method ;
info . options . headers = this . _mergeHeaders ( headers );
if ( this . userAgent != null ) {
info . options . headers [ 'user-agent' ] = this . userAgent ;
}
info . options . agent = this . _getAgent ( info . parsedUrl );
// gives handlers an opportunity to participate
if ( this . handlers ) {
for ( const handler of this . handlers ) {
handler . prepareRequest ( info . options );
}
}
return info ;
}
_mergeHeaders ( headers ) {
if ( this . requestOptions && this . requestOptions . headers ) {
return Object . assign ({}, lowercaseKeys ( this . requestOptions . headers ), lowercaseKeys ( headers || {}));
}
return lowercaseKeys ( headers || {});
}
2025-12-25 10:58:28 +01:00
/**
* Gets an existing header value or returns a default.
* Handles converting number header values to strings since HTTP headers must be strings.
* Note: This returns string | string[] since some headers can have multiple values.
* For headers that must always be a single string (like Content-Type), use the
* specialized _getExistingOrDefaultContentTypeHeader method instead.
*/
2022-10-21 16:52:45 +02:00
_getExistingOrDefaultHeader ( additionalHeaders , header , _default ) {
let clientHeader ;
if ( this . requestOptions && this . requestOptions . headers ) {
2025-12-25 10:58:28 +01:00
const headerValue = lowercaseKeys ( this . requestOptions . headers )[ header ];
if ( headerValue ) {
clientHeader =
typeof headerValue === 'number' ? headerValue . toString () : headerValue ;
}
2022-10-21 16:52:45 +02:00
}
2025-12-25 10:58:28 +01:00
const additionalValue = additionalHeaders [ header ];
if ( additionalValue !== undefined ) {
return typeof additionalValue === 'number'
? additionalValue . toString ()
: additionalValue ;
}
if ( clientHeader !== undefined ) {
return clientHeader ;
}
return _default ;
}
/**
* Specialized version of _getExistingOrDefaultHeader for Content-Type header.
* Always returns a single string (not an array) since Content-Type should be a single value.
* Converts arrays to comma-separated strings and numbers to strings to ensure type safety.
* This was split from _getExistingOrDefaultHeader to provide stricter typing for callers
* that assign the result to places expecting a string (e.g., additionalHeaders[Headers.ContentType]).
*/
_getExistingOrDefaultContentTypeHeader ( additionalHeaders , _default ) {
let clientHeader ;
if ( this . requestOptions && this . requestOptions . headers ) {
const headerValue = lowercaseKeys ( this . requestOptions . headers )[ Headers . ContentType ];
if ( headerValue ) {
if ( typeof headerValue === 'number' ) {
clientHeader = String ( headerValue );
}
else if ( Array . isArray ( headerValue )) {
clientHeader = headerValue . join ( ', ' );
}
else {
clientHeader = headerValue ;
}
}
}
const additionalValue = additionalHeaders [ Headers . ContentType ];
// Return the first non-undefined value, converting numbers or arrays to strings if necessary
if ( additionalValue !== undefined ) {
if ( typeof additionalValue === 'number' ) {
return String ( additionalValue );
}
else if ( Array . isArray ( additionalValue )) {
return additionalValue . join ( ', ' );
}
else {
return additionalValue ;
}
}
if ( clientHeader !== undefined ) {
return clientHeader ;
}
return _default ;
2022-10-21 16:52:45 +02:00
}
_getAgent ( parsedUrl ) {
let agent ;
const proxyUrl = pm . getProxyUrl ( parsedUrl );
const useProxy = proxyUrl && proxyUrl . hostname ;
if ( this . _keepAlive && useProxy ) {
agent = this . _proxyAgent ;
}
2025-06-13 19:44:16 +02:00
if ( ! useProxy ) {
2022-10-21 16:52:45 +02:00
agent = this . _agent ;
}
// if agent is already assigned use that agent.
if ( agent ) {
return agent ;
}
const usingSsl = parsedUrl . protocol === 'https:' ;
let maxSockets = 100 ;
if ( this . requestOptions ) {
maxSockets = this . requestOptions . maxSockets || http . globalAgent . maxSockets ;
}
// This is `useProxy` again, but we need to check `proxyURl` directly for TypeScripts's flow analysis.
if ( proxyUrl && proxyUrl . hostname ) {
const agentOptions = {
maxSockets ,
keepAlive : this . _keepAlive ,
proxy : Object . assign ( Object . assign ({}, (( proxyUrl . username || proxyUrl . password ) && {
proxyAuth : ` ${ proxyUrl . username } : ${ proxyUrl . password } `
})), { host : proxyUrl . hostname , port : proxyUrl . port })
};
let tunnelAgent ;
const overHttps = proxyUrl . protocol === 'https:' ;
if ( usingSsl ) {
tunnelAgent = overHttps ? tunnel . httpsOverHttps : tunnel . httpsOverHttp ;
}
else {
tunnelAgent = overHttps ? tunnel . httpOverHttps : tunnel . httpOverHttp ;
}
agent = tunnelAgent ( agentOptions );
this . _proxyAgent = agent ;
}
2025-06-13 19:44:16 +02:00
// if tunneling agent isn't assigned create a new agent
if ( ! agent ) {
2022-10-21 16:52:45 +02:00
const options = { keepAlive : this . _keepAlive , maxSockets };
agent = usingSsl ? new https . Agent ( options ) : new http . Agent ( options );
this . _agent = agent ;
}
if ( usingSsl && this . _ignoreSslError ) {
// we don't want to set NODE_TLS_REJECT_UNAUTHORIZED=0 since that will affect request for entire process
// http.RequestOptions doesn't expose a way to modify RequestOptions.agent.options
// we have to cast it to any and change it directly
agent . options = Object . assign ( agent . options || {}, {
rejectUnauthorized : false
});
}
return agent ;
}
2025-06-13 19:44:16 +02:00
_getProxyAgentDispatcher ( parsedUrl , proxyUrl ) {
let proxyAgent ;
if ( this . _keepAlive ) {
proxyAgent = this . _proxyAgentDispatcher ;
}
// if agent is already assigned use that agent.
if ( proxyAgent ) {
return proxyAgent ;
}
const usingSsl = parsedUrl . protocol === 'https:' ;
2026-01-30 13:31:20 +01:00
proxyAgent = new ProxyAgent ( Object . assign ({ uri : proxyUrl . href , pipelining : ! this . _keepAlive ? 0 : 1 }, (( proxyUrl . username || proxyUrl . password ) && {
2025-06-13 19:44:16 +02:00
token : `Basic ${ Buffer . from ( ` ${ proxyUrl . username } : ${ proxyUrl . password } ` ). toString ( 'base64' ) } `
})));
this . _proxyAgentDispatcher = proxyAgent ;
if ( usingSsl && this . _ignoreSslError ) {
// we don't want to set NODE_TLS_REJECT_UNAUTHORIZED=0 since that will affect request for entire process
// http.RequestOptions doesn't expose a way to modify RequestOptions.agent.options
// we have to cast it to any and change it directly
proxyAgent . options = Object . assign ( proxyAgent . options . requestTls || {}, {
rejectUnauthorized : false
});
}
return proxyAgent ;
}
2026-01-09 14:32:48 +01:00
_getUserAgentWithOrchestrationId ( userAgent ) {
const baseUserAgent = userAgent || 'actions/http-client' ;
const orchId = process . env [ 'ACTIONS_ORCHESTRATION_ID' ];
if ( orchId ) {
// Sanitize the orchestration ID to ensure it contains only valid characters
// Valid characters: 0-9, a-z, _, -, .
const sanitizedId = orchId . replace ( /[^a-z0-9_.-]/gi , '_' );
return ` ${ baseUserAgent } actions_orchestration_id/ ${ sanitizedId } ` ;
}
return baseUserAgent ;
}
2022-10-21 16:52:45 +02:00
_performExponentialBackoff ( retryNumber ) {
return __awaiter ( this , void 0 , void 0 , function * () {
retryNumber = Math . min ( ExponentialBackoffCeiling , retryNumber );
const ms = ExponentialBackoffTimeSlice * Math . pow ( 2 , retryNumber );
return new Promise ( resolve => setTimeout (() => resolve (), ms ));
});
}
_processResponse ( res , options ) {
return __awaiter ( this , void 0 , void 0 , function * () {
return new Promise (( resolve , reject ) => __awaiter ( this , void 0 , void 0 , function * () {
const statusCode = res . message . statusCode || 0 ;
const response = {
statusCode ,
result : null ,
headers : {}
};
// not found leads to null obj returned
if ( statusCode === HttpCodes . NotFound ) {
resolve ( response );
}
// get the result from the body
function dateTimeDeserializer ( key , value ) {
if ( typeof value === 'string' ) {
const a = new Date ( value );
if ( ! isNaN ( a . valueOf ())) {
return a ;
}
}
return value ;
}
let obj ;
let contents ;
try {
contents = yield res . readBody ();
if ( contents && contents . length > 0 ) {
if ( options && options . deserializeDates ) {
obj = JSON . parse ( contents , dateTimeDeserializer );
}
else {
obj = JSON . parse ( contents );
}
response . result = obj ;
}
response . headers = res . message . headers ;
}
catch ( err ) {
// Invalid resource (contents not json); leaving result obj null
}
// note that 3xx redirects are handled by the http layer.
if ( statusCode > 299 ) {
let msg ;
// if exception/error in body, attempt to get better error
if ( obj && obj . message ) {
msg = obj . message ;
}
else if ( contents && contents . length > 0 ) {
// it may be the case that the exception is in the body message as string
msg = contents ;
}
else {
msg = `Failed request: ( ${ statusCode } )` ;
}
const err = new HttpClientError ( msg , statusCode );
err . result = response . result ;
reject ( err );
}
else {
resolve ( response );
}
}));
});
}
}
const lowercaseKeys = ( obj ) => Object . keys ( obj ). reduce (( c , k ) => (( c [ k . toLowerCase ()] = obj [ k ]), c ), {});
//# sourceMappingURL=index.js.map