Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F101407821
http.js
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Mon, Feb 10, 04:06
Size
18 KB
Mime Type
text/x-java
Expires
Wed, Feb 12, 04:06 (1 d, 9 h)
Engine
blob
Format
Raw Data
Handle
24154565
Attached To
rOACCT Open Access Compliance Check Tool (OACCT)
http.js
View Options
'use strict'
;
import
utils
from
'./../utils.js'
;
import
settle
from
'./../core/settle.js'
;
import
buildFullPath
from
'../core/buildFullPath.js'
;
import
buildURL
from
'./../helpers/buildURL.js'
;
import
{
getProxyForUrl
}
from
'proxy-from-env'
;
import
http
from
'http'
;
import
https
from
'https'
;
import
followRedirects
from
'follow-redirects'
;
import
zlib
from
'zlib'
;
import
{
VERSION
}
from
'../env/data.js'
;
import
transitionalDefaults
from
'../defaults/transitional.js'
;
import
AxiosError
from
'../core/AxiosError.js'
;
import
CanceledError
from
'../cancel/CanceledError.js'
;
import
platform
from
'../platform/index.js'
;
import
fromDataURI
from
'../helpers/fromDataURI.js'
;
import
stream
from
'stream'
;
import
AxiosHeaders
from
'../core/AxiosHeaders.js'
;
import
AxiosTransformStream
from
'../helpers/AxiosTransformStream.js'
;
import
EventEmitter
from
'events'
;
const
zlibOptions
=
{
flush
:
zlib
.
constants
.
Z_SYNC_FLUSH
,
finishFlush
:
zlib
.
constants
.
Z_SYNC_FLUSH
};
const
brotliOptions
=
{
flush
:
zlib
.
constants
.
BROTLI_OPERATION_FLUSH
,
finishFlush
:
zlib
.
constants
.
BROTLI_OPERATION_FLUSH
}
const
isBrotliSupported
=
utils
.
isFunction
(
zlib
.
createBrotliDecompress
);
const
{
http
:
httpFollow
,
https
:
httpsFollow
}
=
followRedirects
;
const
isHttps
=
/https:?/
;
const
supportedProtocols
=
platform
.
protocols
.
map
(
protocol
=>
{
return
protocol
+
':'
;
});
/**
* If the proxy or config beforeRedirects functions are defined, call them with the options
* object.
*
* @param {Object<string, any>} options - The options object that was passed to the request.
*
* @returns {Object<string, any>}
*/
function
dispatchBeforeRedirect
(
options
)
{
if
(
options
.
beforeRedirects
.
proxy
)
{
options
.
beforeRedirects
.
proxy
(
options
);
}
if
(
options
.
beforeRedirects
.
config
)
{
options
.
beforeRedirects
.
config
(
options
);
}
}
/**
* If the proxy or config afterRedirects functions are defined, call them with the options
*
* @param {http.ClientRequestArgs} options
* @param {AxiosProxyConfig} configProxy configuration from Axios options object
* @param {string} location
*
* @returns {http.ClientRequestArgs}
*/
function
setProxy
(
options
,
configProxy
,
location
)
{
let
proxy
=
configProxy
;
if
(
!
proxy
&&
proxy
!==
false
)
{
const
proxyUrl
=
getProxyForUrl
(
location
);
if
(
proxyUrl
)
{
proxy
=
new
URL
(
proxyUrl
);
}
}
if
(
proxy
)
{
// Basic proxy authorization
if
(
proxy
.
username
)
{
proxy
.
auth
=
(
proxy
.
username
||
''
)
+
':'
+
(
proxy
.
password
||
''
);
}
if
(
proxy
.
auth
)
{
// Support proxy auth object form
if
(
proxy
.
auth
.
username
||
proxy
.
auth
.
password
)
{
proxy
.
auth
=
(
proxy
.
auth
.
username
||
''
)
+
':'
+
(
proxy
.
auth
.
password
||
''
);
}
const
base64
=
Buffer
.
from
(
proxy
.
auth
,
'utf8'
)
.
toString
(
'base64'
);
options
.
headers
[
'Proxy-Authorization'
]
=
'Basic '
+
base64
;
}
options
.
headers
.
host
=
options
.
hostname
+
(
options
.
port
?
':'
+
options
.
port
:
''
);
const
proxyHost
=
proxy
.
hostname
||
proxy
.
host
;
options
.
hostname
=
proxyHost
;
// Replace 'host' since options is not a URL object
options
.
host
=
proxyHost
;
options
.
port
=
proxy
.
port
;
options
.
path
=
location
;
if
(
proxy
.
protocol
)
{
options
.
protocol
=
proxy
.
protocol
.
includes
(
':'
)
?
proxy
.
protocol
:
`
$
{
proxy
.
protocol
}
:
`
;
}
}
options
.
beforeRedirects
.
proxy
=
function
beforeRedirect
(
redirectOptions
)
{
// Configure proxy for redirected request, passing the original config proxy to apply
// the exact same logic as if the redirected request was performed by axios directly.
setProxy
(
redirectOptions
,
configProxy
,
redirectOptions
.
href
);
};
}
const
isHttpAdapterSupported
=
typeof
process
!==
'undefined'
&&
utils
.
kindOf
(
process
)
===
'process'
;
/*eslint consistent-return:0*/
export
default
isHttpAdapterSupported
&&
function
httpAdapter
(
config
)
{
return
new
Promise
(
function
dispatchHttpRequest
(
resolvePromise
,
rejectPromise
)
{
let
data
=
config
.
data
;
const
responseType
=
config
.
responseType
;
const
responseEncoding
=
config
.
responseEncoding
;
const
method
=
config
.
method
.
toUpperCase
();
let
isFinished
;
let
isDone
;
let
rejected
=
false
;
let
req
;
// temporary internal emitter until the AxiosRequest class will be implemented
const
emitter
=
new
EventEmitter
();
function
onFinished
()
{
if
(
isFinished
)
return
;
isFinished
=
true
;
if
(
config
.
cancelToken
)
{
config
.
cancelToken
.
unsubscribe
(
abort
);
}
if
(
config
.
signal
)
{
config
.
signal
.
removeEventListener
(
'abort'
,
abort
);
}
emitter
.
removeAllListeners
();
}
function
done
(
value
,
isRejected
)
{
if
(
isDone
)
return
;
isDone
=
true
;
if
(
isRejected
)
{
rejected
=
true
;
onFinished
();
}
isRejected
?
rejectPromise
(
value
)
:
resolvePromise
(
value
);
}
const
resolve
=
function
resolve
(
value
)
{
done
(
value
);
};
const
reject
=
function
reject
(
value
)
{
done
(
value
,
true
);
};
function
abort
(
reason
)
{
emitter
.
emit
(
'abort'
,
!
reason
||
reason
.
type
?
new
CanceledError
(
null
,
config
,
req
)
:
reason
);
}
emitter
.
once
(
'abort'
,
reject
);
if
(
config
.
cancelToken
||
config
.
signal
)
{
config
.
cancelToken
&&
config
.
cancelToken
.
subscribe
(
abort
);
if
(
config
.
signal
)
{
config
.
signal
.
aborted
?
abort
()
:
config
.
signal
.
addEventListener
(
'abort'
,
abort
);
}
}
// Parse url
const
fullPath
=
buildFullPath
(
config
.
baseURL
,
config
.
url
);
const
parsed
=
new
URL
(
fullPath
);
const
protocol
=
parsed
.
protocol
||
supportedProtocols
[
0
];
if
(
protocol
===
'data:'
)
{
let
convertedData
;
if
(
method
!==
'GET'
)
{
return
settle
(
resolve
,
reject
,
{
status
:
405
,
statusText
:
'method not allowed'
,
headers
:
{},
config
});
}
try
{
convertedData
=
fromDataURI
(
config
.
url
,
responseType
===
'blob'
,
{
Blob
:
config
.
env
&&
config
.
env
.
Blob
});
}
catch
(
err
)
{
throw
AxiosError
.
from
(
err
,
AxiosError
.
ERR_BAD_REQUEST
,
config
);
}
if
(
responseType
===
'text'
)
{
convertedData
=
convertedData
.
toString
(
responseEncoding
);
if
(
!
responseEncoding
||
responseEncoding
===
'utf8'
)
{
data
=
utils
.
stripBOM
(
convertedData
);
}
}
else
if
(
responseType
===
'stream'
)
{
convertedData
=
stream
.
Readable
.
from
(
convertedData
);
}
return
settle
(
resolve
,
reject
,
{
data
:
convertedData
,
status
:
200
,
statusText
:
'OK'
,
headers
:
new
AxiosHeaders
(),
config
});
}
if
(
supportedProtocols
.
indexOf
(
protocol
)
===
-
1
)
{
return
reject
(
new
AxiosError
(
'Unsupported protocol '
+
protocol
,
AxiosError
.
ERR_BAD_REQUEST
,
config
));
}
const
headers
=
AxiosHeaders
.
from
(
config
.
headers
).
normalize
();
// Set User-Agent (required by some servers)
// See https://github.com/axios/axios/issues/69
// User-Agent is specified; handle case where no UA header is desired
// Only set header if it hasn't been set in config
headers
.
set
(
'User-Agent'
,
'axios/'
+
VERSION
,
false
);
const
onDownloadProgress
=
config
.
onDownloadProgress
;
const
onUploadProgress
=
config
.
onUploadProgress
;
const
maxRate
=
config
.
maxRate
;
let
maxUploadRate
=
undefined
;
let
maxDownloadRate
=
undefined
;
// support for https://www.npmjs.com/package/form-data api
if
(
utils
.
isFormData
(
data
)
&&
utils
.
isFunction
(
data
.
getHeaders
))
{
headers
.
set
(
data
.
getHeaders
());
}
else
if
(
data
&&
!
utils
.
isStream
(
data
))
{
if
(
Buffer
.
isBuffer
(
data
))
{
// Nothing to do...
}
else
if
(
utils
.
isArrayBuffer
(
data
))
{
data
=
Buffer
.
from
(
new
Uint8Array
(
data
));
}
else
if
(
utils
.
isString
(
data
))
{
data
=
Buffer
.
from
(
data
,
'utf-8'
);
}
else
{
return
reject
(
new
AxiosError
(
'Data after transformation must be a string, an ArrayBuffer, a Buffer, or a Stream'
,
AxiosError
.
ERR_BAD_REQUEST
,
config
));
}
// Add Content-Length header if data exists
headers
.
set
(
'Content-Length'
,
data
.
length
,
false
);
if
(
config
.
maxBodyLength
>
-
1
&&
data
.
length
>
config
.
maxBodyLength
)
{
return
reject
(
new
AxiosError
(
'Request body larger than maxBodyLength limit'
,
AxiosError
.
ERR_BAD_REQUEST
,
config
));
}
}
const
contentLength
=
utils
.
toFiniteNumber
(
headers
.
getContentLength
());
if
(
utils
.
isArray
(
maxRate
))
{
maxUploadRate
=
maxRate
[
0
];
maxDownloadRate
=
maxRate
[
1
];
}
else
{
maxUploadRate
=
maxDownloadRate
=
maxRate
;
}
if
(
data
&&
(
onUploadProgress
||
maxUploadRate
))
{
if
(
!
utils
.
isStream
(
data
))
{
data
=
stream
.
Readable
.
from
(
data
,
{
objectMode
:
false
});
}
data
=
stream
.
pipeline
([
data
,
new
AxiosTransformStream
({
length
:
contentLength
,
maxRate
:
utils
.
toFiniteNumber
(
maxUploadRate
)
})],
utils
.
noop
);
onUploadProgress
&&
data
.
on
(
'progress'
,
progress
=>
{
onUploadProgress
(
Object
.
assign
(
progress
,
{
upload
:
true
}));
});
}
// HTTP basic authentication
let
auth
=
undefined
;
if
(
config
.
auth
)
{
const
username
=
config
.
auth
.
username
||
''
;
const
password
=
config
.
auth
.
password
||
''
;
auth
=
username
+
':'
+
password
;
}
if
(
!
auth
&&
parsed
.
username
)
{
const
urlUsername
=
parsed
.
username
;
const
urlPassword
=
parsed
.
password
;
auth
=
urlUsername
+
':'
+
urlPassword
;
}
auth
&&
headers
.
delete
(
'authorization'
);
let
path
;
try
{
path
=
buildURL
(
parsed
.
pathname
+
parsed
.
search
,
config
.
params
,
config
.
paramsSerializer
).
replace
(
/^\?/
,
''
);
}
catch
(
err
)
{
const
customErr
=
new
Error
(
err
.
message
);
customErr
.
config
=
config
;
customErr
.
url
=
config
.
url
;
customErr
.
exists
=
true
;
return
reject
(
customErr
);
}
headers
.
set
(
'Accept-Encoding'
,
'gzip, compress, deflate'
+
(
isBrotliSupported
?
', br'
:
''
),
false
);
const
options
=
{
path
,
method
:
method
,
headers
:
headers
.
toJSON
(),
agents
:
{
http
:
config
.
httpAgent
,
https
:
config
.
httpsAgent
},
auth
,
protocol
,
beforeRedirect
:
dispatchBeforeRedirect
,
beforeRedirects
:
{}
};
if
(
config
.
socketPath
)
{
options
.
socketPath
=
config
.
socketPath
;
}
else
{
options
.
hostname
=
parsed
.
hostname
;
options
.
port
=
parsed
.
port
;
setProxy
(
options
,
config
.
proxy
,
protocol
+
'//'
+
parsed
.
hostname
+
(
parsed
.
port
?
':'
+
parsed
.
port
:
''
)
+
options
.
path
);
}
let
transport
;
const
isHttpsRequest
=
isHttps
.
test
(
options
.
protocol
);
options
.
agent
=
isHttpsRequest
?
config
.
httpsAgent
:
config
.
httpAgent
;
if
(
config
.
transport
)
{
transport
=
config
.
transport
;
}
else
if
(
config
.
maxRedirects
===
0
)
{
transport
=
isHttpsRequest
?
https
:
http
;
}
else
{
if
(
config
.
maxRedirects
)
{
options
.
maxRedirects
=
config
.
maxRedirects
;
}
if
(
config
.
beforeRedirect
)
{
options
.
beforeRedirects
.
config
=
config
.
beforeRedirect
;
}
transport
=
isHttpsRequest
?
httpsFollow
:
httpFollow
;
}
if
(
config
.
maxBodyLength
>
-
1
)
{
options
.
maxBodyLength
=
config
.
maxBodyLength
;
}
else
{
// follow-redirects does not skip comparison, so it should always succeed for axios -1 unlimited
options
.
maxBodyLength
=
Infinity
;
}
if
(
config
.
insecureHTTPParser
)
{
options
.
insecureHTTPParser
=
config
.
insecureHTTPParser
;
}
// Create the request
req
=
transport
.
request
(
options
,
function
handleResponse
(
res
)
{
if
(
req
.
destroyed
)
return
;
const
streams
=
[
res
];
const
responseLength
=
+
res
.
headers
[
'content-length'
];
if
(
onDownloadProgress
)
{
const
transformStream
=
new
AxiosTransformStream
({
length
:
utils
.
toFiniteNumber
(
responseLength
),
maxRate
:
utils
.
toFiniteNumber
(
maxDownloadRate
)
});
onDownloadProgress
&&
transformStream
.
on
(
'progress'
,
progress
=>
{
onDownloadProgress
(
Object
.
assign
(
progress
,
{
download
:
true
}));
});
streams
.
push
(
transformStream
);
}
// decompress the response body transparently if required
let
responseStream
=
res
;
// return the last request in case of redirects
const
lastRequest
=
res
.
req
||
req
;
// if decompress disabled we should not decompress
if
(
config
.
decompress
!==
false
&&
res
.
headers
[
'content-encoding'
])
{
// if no content, but headers still say that it is encoded,
// remove the header not confuse downstream operations
if
(
method
===
'HEAD'
||
res
.
statusCode
===
204
)
{
delete
res
.
headers
[
'content-encoding'
];
}
switch
(
res
.
headers
[
'content-encoding'
])
{
/*eslint default-case:0*/
case
'gzip'
:
case
'x-gzip'
:
case
'compress'
:
case
'x-compress'
:
case
'deflate'
:
// add the unzipper to the body stream processing pipeline
streams
.
push
(
zlib
.
createUnzip
(
zlibOptions
));
// remove the content-encoding in order to not confuse downstream operations
delete
res
.
headers
[
'content-encoding'
];
break
;
case
'br'
:
if
(
isBrotliSupported
)
{
streams
.
push
(
zlib
.
createBrotliDecompress
(
brotliOptions
));
delete
res
.
headers
[
'content-encoding'
];
}
}
}
responseStream
=
streams
.
length
>
1
?
stream
.
pipeline
(
streams
,
utils
.
noop
)
:
streams
[
0
];
const
offListeners
=
stream
.
finished
(
responseStream
,
()
=>
{
offListeners
();
onFinished
();
});
const
response
=
{
status
:
res
.
statusCode
,
statusText
:
res
.
statusMessage
,
headers
:
new
AxiosHeaders
(
res
.
headers
),
config
,
request
:
lastRequest
};
if
(
responseType
===
'stream'
)
{
response
.
data
=
responseStream
;
settle
(
resolve
,
reject
,
response
);
}
else
{
const
responseBuffer
=
[];
let
totalResponseBytes
=
0
;
responseStream
.
on
(
'data'
,
function
handleStreamData
(
chunk
)
{
responseBuffer
.
push
(
chunk
);
totalResponseBytes
+=
chunk
.
length
;
// make sure the content length is not over the maxContentLength if specified
if
(
config
.
maxContentLength
>
-
1
&&
totalResponseBytes
>
config
.
maxContentLength
)
{
// stream.destroy() emit aborted event before calling reject() on Node.js v16
rejected
=
true
;
responseStream
.
destroy
();
reject
(
new
AxiosError
(
'maxContentLength size of '
+
config
.
maxContentLength
+
' exceeded'
,
AxiosError
.
ERR_BAD_RESPONSE
,
config
,
lastRequest
));
}
});
responseStream
.
on
(
'aborted'
,
function
handlerStreamAborted
()
{
if
(
rejected
)
{
return
;
}
const
err
=
new
AxiosError
(
'maxContentLength size of '
+
config
.
maxContentLength
+
' exceeded'
,
AxiosError
.
ERR_BAD_RESPONSE
,
config
,
lastRequest
);
responseStream
.
destroy
(
err
);
reject
(
err
);
});
responseStream
.
on
(
'error'
,
function
handleStreamError
(
err
)
{
if
(
req
.
destroyed
)
return
;
reject
(
AxiosError
.
from
(
err
,
null
,
config
,
lastRequest
));
});
responseStream
.
on
(
'end'
,
function
handleStreamEnd
()
{
try
{
let
responseData
=
responseBuffer
.
length
===
1
?
responseBuffer
[
0
]
:
Buffer
.
concat
(
responseBuffer
);
if
(
responseType
!==
'arraybuffer'
)
{
responseData
=
responseData
.
toString
(
responseEncoding
);
if
(
!
responseEncoding
||
responseEncoding
===
'utf8'
)
{
responseData
=
utils
.
stripBOM
(
responseData
);
}
}
response
.
data
=
responseData
;
}
catch
(
err
)
{
reject
(
AxiosError
.
from
(
err
,
null
,
config
,
response
.
request
,
response
));
}
settle
(
resolve
,
reject
,
response
);
});
}
emitter
.
once
(
'abort'
,
err
=>
{
if
(
!
responseStream
.
destroyed
)
{
responseStream
.
emit
(
'error'
,
err
);
responseStream
.
destroy
();
}
});
});
emitter
.
once
(
'abort'
,
err
=>
{
reject
(
err
);
req
.
destroy
(
err
);
});
// Handle errors
req
.
on
(
'error'
,
function
handleRequestError
(
err
)
{
// @todo remove
// if (req.aborted && err.code !== AxiosError.ERR_FR_TOO_MANY_REDIRECTS) return;
reject
(
AxiosError
.
from
(
err
,
null
,
config
,
req
));
});
// set tcp keep alive to prevent drop connection by peer
req
.
on
(
'socket'
,
function
handleRequestSocket
(
socket
)
{
// default interval of sending ack packet is 1 minute
socket
.
setKeepAlive
(
true
,
1000
*
60
);
});
// Handle request timeout
if
(
config
.
timeout
)
{
// This is forcing a int timeout to avoid problems if the `req` interface doesn't handle other types.
const
timeout
=
parseInt
(
config
.
timeout
,
10
);
if
(
isNaN
(
timeout
))
{
reject
(
new
AxiosError
(
'error trying to parse `config.timeout` to int'
,
AxiosError
.
ERR_BAD_OPTION_VALUE
,
config
,
req
));
return
;
}
// Sometime, the response will be very slow, and does not respond, the connect event will be block by event loop system.
// And timer callback will be fired, and abort() will be invoked before connection, then get "socket hang up" and code ECONNRESET.
// At this time, if we have a large number of request, nodejs will hang up some socket on background. and the number will up and up.
// And then these socket which be hang up will devouring CPU little by little.
// ClientRequest.setTimeout will be fired on the specify milliseconds, and can make sure that abort() will be fired after connect.
req
.
setTimeout
(
timeout
,
function
handleRequestTimeout
()
{
if
(
isDone
)
return
;
let
timeoutErrorMessage
=
config
.
timeout
?
'timeout of '
+
config
.
timeout
+
'ms exceeded'
:
'timeout exceeded'
;
const
transitional
=
config
.
transitional
||
transitionalDefaults
;
if
(
config
.
timeoutErrorMessage
)
{
timeoutErrorMessage
=
config
.
timeoutErrorMessage
;
}
reject
(
new
AxiosError
(
timeoutErrorMessage
,
transitional
.
clarifyTimeoutError
?
AxiosError
.
ETIMEDOUT
:
AxiosError
.
ECONNABORTED
,
config
,
req
));
abort
();
});
}
// Send the request
if
(
utils
.
isStream
(
data
))
{
let
ended
=
false
;
let
errored
=
false
;
data
.
on
(
'end'
,
()
=>
{
ended
=
true
;
});
data
.
once
(
'error'
,
err
=>
{
errored
=
true
;
req
.
destroy
(
err
);
});
data
.
on
(
'close'
,
()
=>
{
if
(
!
ended
&&
!
errored
)
{
abort
(
new
CanceledError
(
'Request stream has been aborted'
,
config
,
req
));
}
});
data
.
pipe
(
req
);
}
else
{
req
.
end
(
data
);
}
});
}
export
const
__setProxy
=
setProxy
;
Event Timeline
Log In to Comment