download timeouts
- 8s by default
- only for curl atm.
1 parent 1e368ff commit 95eb15c9f72a9d8428146f45f188cf09d22a69d6
@Martin Nowak Martin Nowak authored on 15 Jan 2018
Showing 2 changed files
View
36
source/dub/internal/utils.d
Downloads a file from the specified URL.
 
Any redirects will be followed until the actual file resource is reached or if the redirection
limit of 10 is reached. Note that only HTTP(S) is currently supported.
 
The download times out if a connection cannot be established within
`timeout` ms, or if the average transfer rate drops below 10 bytes / s for
more than `timeout` seconds. Pass `0` as `timeout` to disable both timeout
mechanisms.
 
Note: Timeouts are only implemented when curl is used (DubUseCurl).
*/
void download(string url, string filename)
void download(string url, string filename, uint timeout = 8)
{
version(DubUseCurl) {
auto conn = HTTP();
setupHTTPClient(conn);
setupHTTPClient(conn, timeout);
logDebug("Storing %s...", url);
static if (__VERSION__ <= 2075)
{
try
vibe.inet.urltransfer.download(url, filename);
} else assert(false);
}
/// ditto
void download(URL url, NativePath filename)
{
download(url.toString(), filename.toNativeString());
void download(URL url, NativePath filename, uint timeout = 8)
{
download(url.toString(), filename.toNativeString(), timeout);
}
/// ditto
ubyte[] download(string url)
ubyte[] download(string url, uint timeout = 8)
{
version(DubUseCurl) {
auto conn = HTTP();
setupHTTPClient(conn);
setupHTTPClient(conn, timeout);
logDebug("Getting %s...", url);
static if (__VERSION__ <= 2075)
{
try
return ret;
} else assert(false);
}
/// ditto
ubyte[] download(URL url)
{
return download(url.toString());
ubyte[] download(URL url, uint timeout = 8)
{
return download(url.toString(), timeout);
}
 
/// Returns the current DUB version in semantic version format
string getDUBVersion()
return verstr;
}
 
version(DubUseCurl) {
void setupHTTPClient(ref HTTP conn)
void setupHTTPClient(ref HTTP conn, uint timeout)
{
static if( is(typeof(&conn.verifyPeer)) )
conn.verifyPeer = false;
 
auto noProxy = environment.get("no_proxy", null);
if (noProxy.length) conn.handle.set(CurlOption.noproxy, noProxy);
 
conn.handle.set(CurlOption.encoding, "");
if (timeout) {
// connection (TLS+TCP) times out after 8s
conn.handle.set(CurlOption.connecttimeout, timeout);
// transfers time out after 8s below 10 byte/s
conn.handle.set(CurlOption.low_speed_limit, 10);
conn.handle.set(CurlOption.low_speed_time, 5);
}
 
conn.addRequestHeader("User-Agent", "dub/"~getDUBVersion()~" (std.net.curl; +https://github.com/rejectedsoftware/dub)");
}
}
View
44
test/timeout.sh 0 → 100755
#!/usr/bin/env bash
 
. $(dirname "${BASH_SOURCE[0]}")/common.sh
 
PORT=$(($$ + 1024)) # PID + 1024
 
log ' Testing unconnectable registry'
if timeout 1s $DUB fetch dub --skip-registry=all --registry=http://localhost:$PORT; then
die 'Fetching from unconnectable registry should fail.'
elif [ $? -eq 124 ]; then
die 'Fetching from unconnectable registry should fail immediately.'
fi
 
log ' Testing non-responding registry'
cat | nc --listen $PORT >/dev/null &
PID=$!
if timeout 10s $DUB fetch dub --skip-registry=all --registry=http://localhost:$PORT; then
die 'Fetching from non-responding registry should fail.'
elif [ $? -eq 124 ]; then
die 'Fetching from non-responding registry should time-out within 8s.'
fi
kill $PID 2>/dev/null || true
 
log ' Testing too slow registry'
{
res=$(printf 'HTTP/1.1 200 OK\r
Server: dummy\r
Content-Type: application/json\r
Content-Length: 2\r
\r
{}')
for i in $(seq 0 $((${#res} - 1))); do
echo -n "${res:$i:1}"
sleep 1
done
} | nc --listen $PORT >/dev/null &
PID=$!
if timeout 10s time $DUB fetch dub --skip-registry=all --registry=http://localhost:$PORT; then
die 'Fetching from too slow registry should fail.'
elif [ $? -eq 124 ]; then
die 'Fetching from too slow registry should time-out within 8s.'
fi
kill $PID 2>/dev/null || true