Skip to content

Instantly share code, notes, and snippets.

@PRO-2684
Last active September 6, 2026 14:03
Show Gist options
  • Select an option

  • Save PRO-2684/c1f59bf10990ee02abf91ca008375b85 to your computer and use it in GitHub Desktop.

Select an option

Save PRO-2684/c1f59bf10990ee02abf91ca008375b85 to your computer and use it in GitHub Desktop.
dlwrap

dlwrap

Wraps a command, so invocations to curl and wget are translated to aria2c.

Install

install -Dm755 dlwrap.sh ~/.local/bin/dlwrap

mkdir -p ~/.local/libexec/dlwrap
ln -sf ~/.local/bin/dlwrap ~/.local/libexec/dlwrap/curl
ln -sf ~/.local/bin/dlwrap ~/.local/libexec/dlwrap/wget

Usage

# aria2 acceleration, otherwise respect updater's quietness
dlwrap -- some-updater

# force progress even if updater uses curl -s / wget -q
dlwrap --progress -- some-updater

# much noisier downloader diagnostics
dlwrap --verbose -- some-updater

# tune policy
dlwrap \
  --progress \
  --connections 8 \
  --retries 20 \
  --retry-wait 3 \
  --timeout 60 \
  --connect-timeout 15 \
  -- some-updater

Credits

#!/usr/bin/env bash
# dlwrap: run an updater with curl/wget transparently accelerated by aria2c.
# Install this file as ~/.local/bin/dlwrap and symlink it as
# ~/.local/libexec/dlwrap/{curl,wget}.
set -u
prog=${0##*/}
_die() {
printf 'dlwrap: %s\n' "$*" >&2
exit 2
}
_is_uint() {
[[ ${1:-} =~ ^[0-9]+$ ]]
}
_find_command_excluding() {
local name=$1 exclude=$2 dir candidate
local old_ifs=$IFS
IFS=:
for dir in $PATH; do
[ -n "$dir" ] || dir=.
[ "$dir" = "$exclude" ] && continue
candidate=$dir/$name
if [ -f "$candidate" ] && [ -x "$candidate" ]; then
printf '%s\n' "$candidate"
IFS=$old_ifs
return 0
fi
done
IFS=$old_ifs
return 1
}
_native_curl() {
local real=${DLWRAP_REAL_CURL:-}
[ -n "$real" ] || _die 'curl fallback required, but no real curl was found'
local extra=()
if [ "${DLWRAP_VERBOSE:-0}" = 1 ]; then
extra+=(--no-silent --show-error --verbose)
elif [ "${DLWRAP_FORCE_PROGRESS:-0}" = 1 ]; then
extra+=(--no-silent --show-error)
fi
exec "$real" "$@" "${extra[@]}"
}
_native_wget() {
local real=${DLWRAP_REAL_WGET:-}
[ -n "$real" ] || _die 'wget fallback required, but no real wget was found'
local extra=()
if [ "${DLWRAP_VERBOSE:-0}" = 1 ]; then
extra+=(--verbose --show-progress --progress=bar:force:noscroll)
elif [ "${DLWRAP_FORCE_PROGRESS:-0}" = 1 ]; then
extra+=(--show-progress --progress=bar:force:noscroll)
fi
exec "$real" "$@" "${extra[@]}"
}
_aria_base() {
ARIA=(
"${DLWRAP_ARIA2C:?dlwrap: DLWRAP_ARIA2C is not set}"
-x "${DLWRAP_CONNECTIONS:-16}"
-s "${DLWRAP_CONNECTIONS:-16}"
"--max-tries=${DLWRAP_RETRIES:-10}"
"--retry-wait=${DLWRAP_RETRY_WAIT:-2}"
"--timeout=${DLWRAP_TIMEOUT:-30}"
"--connect-timeout=${DLWRAP_CONNECT_TIMEOUT:-10}"
--auto-file-renaming=false
--allow-overwrite=true
--remove-control-file=true
--stderr=true
)
if [ "${DLWRAP_VERBOSE:-0}" = 1 ]; then
ARIA+=(--quiet=false --show-console-readout=true --summary-interval=1 --console-log-level=info)
elif [ "${DLWRAP_FORCE_PROGRESS:-0}" = 1 ]; then
ARIA+=(--quiet=false --show-console-readout=true --summary-interval=1 --console-log-level=warn)
fi
}
_run_aria() {
local quiet=$1 output=$2 url=$3
shift 3
local extras=("$@")
_aria_base
if [ "${DLWRAP_FORCE_PROGRESS:-0}" != 1 ] && [ "${DLWRAP_VERBOSE:-0}" != 1 ]; then
if [ "$quiet" = 1 ]; then
ARIA+=(--quiet=true)
else
ARIA+=(--show-console-readout=true --summary-interval=1 --console-log-level=warn)
fi
fi
ARIA+=("${extras[@]}")
if [ -n "$output" ]; then
local dir base
dir=$(dirname -- "$output")
base=$(basename -- "$output")
ARIA+=(-d "$dir" -o "$base")
fi
ARIA+=("$url")
exec "${ARIA[@]}"
}
_run_aria_stdout() {
local quiet=$1 url=$2
shift 2
local extras=("$@")
local tmpdir status
tmpdir=$(mktemp -d "${TMPDIR:-/tmp}/dlwrap.XXXXXX") || _die 'could not create temporary directory'
_aria_base
if [ "${DLWRAP_FORCE_PROGRESS:-0}" != 1 ] && [ "${DLWRAP_VERBOSE:-0}" != 1 ]; then
if [ "$quiet" = 1 ]; then
ARIA+=(--quiet=true)
else
ARIA+=(--show-console-readout=true --summary-interval=1 --console-log-level=warn)
fi
fi
ARIA+=("${extras[@]}" -d "$tmpdir" -o data "$url")
"${ARIA[@]}"
status=$?
if [ "$status" -eq 0 ]; then
cat -- "$tmpdir/data"
status=$?
fi
rm -rf -- "$tmpdir"
return "$status"
}
_shim_curl() {
local original=("$@")
local quiet=0 show_error=0 output='' remote_name=0 url=''
local unsupported=0
local extras=()
local arg value chars c
while [ $# -gt 0 ]; do
arg=$1
shift
case "$arg" in
--)
[ $# -eq 1 ] || unsupported=1
if [ $# -gt 0 ]; then
[ -z "$url" ] || unsupported=1
url=$1
shift
fi
;;
http://*|https://*|ftp://*)
if [ -n "$url" ]; then unsupported=1; else url=$arg; fi
;;
-o|--output)
[ $# -gt 0 ] || { unsupported=1; break; }
output=$1; shift
[ "$output" != '-' ] || unsupported=1
;;
--output=*)
output=${arg#*=}
[ "$output" != '-' ] || unsupported=1
;;
-O|--remote-name)
remote_name=1
;;
-H|--header)
[ $# -gt 0 ] || { unsupported=1; break; }
value=$1; shift
extras+=("--header=$value")
;;
--header=*) extras+=("--header=${arg#*=}") ;;
-A|--user-agent)
[ $# -gt 0 ] || { unsupported=1; break; }
value=$1; shift
extras+=("--user-agent=$value")
;;
--user-agent=*) extras+=("--user-agent=${arg#*=}") ;;
-e|--referer)
[ $# -gt 0 ] || { unsupported=1; break; }
value=$1; shift
extras+=("--referer=$value")
;;
--referer=*) extras+=("--referer=${arg#*=}") ;;
-C|--continue-at)
[ $# -gt 0 ] || { unsupported=1; break; }
value=$1; shift
[ "$value" = '-' ] && extras+=(--continue=true) || unsupported=1
;;
--continue-at=-) extras+=(--continue=true) ;;
-k|--insecure) extras+=(--check-certificate=false) ;;
-4|--ipv4) extras+=(--disable-ipv6=true) ;;
-L|--location|--fail|--retry-all-errors|--retry-connrefused)
;;
--retry|--retry-delay|--connect-timeout)
[ $# -gt 0 ] || { unsupported=1; break; }
shift # dlwrap policy intentionally wins
;;
--retry=*|--retry-delay=*|--connect-timeout=*)
;;
--max-time)
[ $# -gt 0 ] || { unsupported=1; break; }
value=$1; shift
_is_uint "$value" && extras+=("--stop=$value") || unsupported=1
;;
--max-time=*)
value=${arg#*=}
_is_uint "$value" && extras+=("--stop=$value") || unsupported=1
;;
-s|--silent) quiet=1 ;;
-S|--show-error) show_error=1 ;;
-f|-L|-s|-S) ;; # handled by combined-short parser below when combined
-[!-]*)
# Common compact updater form, e.g. -fsSL. Only accept
# single-letter boolean flags we can reproduce safely.
chars=${arg#-}
while [ -n "$chars" ]; do
c=${chars:0:1}
chars=${chars:1}
case "$c" in
f|L) ;;
s) quiet=1 ;;
S) show_error=1 ;;
k) extras+=(--check-certificate=false) ;;
4) extras+=(--disable-ipv6=true) ;;
O) remote_name=1 ;;
*) unsupported=1 ;;
esac
done
;;
*) unsupported=1 ;;
esac
done
[ "$unsupported" = 0 ] || _native_curl "${original[@]}"
[ -n "$url" ] || _native_curl "${original[@]}"
# curl writes to stdout unless -o/-O is present. Buffer simple stdout
# downloads through aria2c; --stream opts back into native streaming.
if [ -z "$output" ] && [ "$remote_name" = 0 ]; then
[ "${DLWRAP_STREAM:-0}" != 1 ] || _native_curl "${original[@]}"
if [ "$quiet" = 1 ] && [ "$show_error" = 1 ] && \
[ "${DLWRAP_FORCE_PROGRESS:-0}" != 1 ] && [ "${DLWRAP_VERBOSE:-0}" != 1 ]; then
quiet=0
extras+=(--show-console-readout=false --summary-interval=0 --console-log-level=error)
fi
_run_aria_stdout "$quiet" "$url" "${extras[@]}"
return $?
fi
if [ "$remote_name" = 1 ]; then
[ -z "$output" ] || _native_curl "${original[@]}"
value=${url%%\#*}
value=${value%%\?*}
value=${value%/}
output=${value##*/}
[ -n "$output" ] || _native_curl "${original[@]}"
fi
# curl -sS suppresses progress but still reports errors. aria2's quiet
# mode suppresses everything, so emulate -sS with error-only logging.
if [ "$quiet" = 1 ] && [ "$show_error" = 1 ] && \
[ "${DLWRAP_FORCE_PROGRESS:-0}" != 1 ] && [ "${DLWRAP_VERBOSE:-0}" != 1 ]; then
quiet=0
extras+=(--show-console-readout=false --summary-interval=0 --console-log-level=error)
fi
_run_aria "$quiet" "$output" "$url" "${extras[@]}"
}
_shim_wget() {
local original=("$@")
local quiet=0 output='' stdout=0 url='' unsupported=0
local extras=()
local arg value
while [ $# -gt 0 ]; do
arg=$1
shift
case "$arg" in
--)
[ $# -eq 1 ] || unsupported=1
if [ $# -gt 0 ]; then
[ -z "$url" ] || unsupported=1
url=$1
shift
fi
;;
http://*|https://*|ftp://*)
if [ -n "$url" ]; then unsupported=1; else url=$arg; fi
;;
-O|--output-document)
[ $# -gt 0 ] || { unsupported=1; break; }
output=$1; shift
if [ "$output" = '-' ]; then stdout=1; output=''; fi
;;
-qO?*)
quiet=1
output=${arg#-qO}
if [ "$output" = '-' ]; then stdout=1; output=''; fi
;;
-O?*)
output=${arg#-O}
if [ "$output" = '-' ]; then stdout=1; output=''; fi
;;
--output-document=*)
output=${arg#*=}
if [ "$output" = '-' ]; then stdout=1; output=''; fi
;;
-q|--quiet) quiet=1 ;;
--show-progress|--progress=*) quiet=0 ;;
-c|--continue) extras+=(--continue=true) ;;
--header=*) extras+=("--header=${arg#*=}") ;;
--header)
[ $# -gt 0 ] || { unsupported=1; break; }
extras+=("--header=$1"); shift
;;
-U|--user-agent)
[ $# -gt 0 ] || { unsupported=1; break; }
extras+=("--user-agent=$1"); shift
;;
--user-agent=*) extras+=("--user-agent=${arg#*=}") ;;
--referer=*) extras+=("--referer=${arg#*=}") ;;
--referer)
[ $# -gt 0 ] || { unsupported=1; break; }
extras+=("--referer=$1"); shift
;;
--load-cookies=*) extras+=("--load-cookies=${arg#*=}") ;;
--load-cookies)
[ $# -gt 0 ] || { unsupported=1; break; }
extras+=("--load-cookies=$1"); shift
;;
--no-check-certificate) extras+=(--check-certificate=false) ;;
-4|--inet4-only) extras+=(--disable-ipv6=true) ;;
-t|-T|--tries|--timeout|--connect-timeout|--read-timeout|--waitretry)
[ $# -gt 0 ] || { unsupported=1; break; }
shift # dlwrap policy intentionally wins
;;
--tries=*|--timeout=*|--connect-timeout=*|--read-timeout=*|--waitretry=*|--retry-connrefused)
;;
--spider|-6|--inet6-only|--content-disposition|--trust-server-names|-nv|--no-verbose)
unsupported=1
;;
*) unsupported=1 ;;
esac
done
[ "$unsupported" = 0 ] || _native_wget "${original[@]}"
[ -n "$url" ] || _native_wget "${original[@]}"
if [ "$stdout" = 1 ]; then
[ "${DLWRAP_STREAM:-0}" != 1 ] || _native_wget "${original[@]}"
_run_aria_stdout "$quiet" "$url" "${extras[@]}"
return $?
fi
# With -O, wget truncates/overwrites the requested file, matching the
# aria2 defaults above. Without -O, let aria2 derive the URL filename.
if [ -z "$output" ]; then
_aria_base
# Plain wget does not clobber an existing filename; it chooses .1, .2, ...
# Override the explicit-output policy from _aria_base for this case.
ARIA+=(--auto-file-renaming=true --allow-overwrite=false --remove-control-file=false)
if [ "${DLWRAP_FORCE_PROGRESS:-0}" != 1 ] && [ "${DLWRAP_VERBOSE:-0}" != 1 ]; then
if [ "$quiet" = 1 ]; then
ARIA+=(--quiet=true)
else
ARIA+=(--show-console-readout=true --summary-interval=1 --console-log-level=warn)
fi
fi
ARIA+=("${extras[@]}" "$url")
exec "${ARIA[@]}"
fi
_run_aria "$quiet" "$output" "$url" "${extras[@]}"
}
_dlwrap_main() {
local progress=${DLWRAP_FORCE_PROGRESS:-0}
local verbose=${DLWRAP_VERBOSE:-0}
local stream=${DLWRAP_STREAM:-0}
local connections=${DLWRAP_CONNECTIONS:-16}
local retries=${DLWRAP_RETRIES:-10}
local retry_wait=${DLWRAP_RETRY_WAIT:-2}
local timeout=${DLWRAP_TIMEOUT:-30}
local connect_timeout=${DLWRAP_CONNECT_TIMEOUT:-10}
local shim_dir=${DLWRAP_SHIM_DIR:-"$HOME/.local/libexec/dlwrap"}
while [ $# -gt 0 ]; do
case "$1" in
-p|--progress) progress=1; shift ;;
-v|--verbose) verbose=1; progress=1; shift ;;
--stream) stream=1; shift ;;
--connections|--retries|--retry-wait|--timeout|--connect-timeout)
local opt=$1
[ $# -ge 2 ] || _die "$opt requires an integer"
_is_uint "$2" || _die "$opt requires a non-negative integer"
case "$opt" in
--connections) connections=$2 ;;
--retries) retries=$2 ;;
--retry-wait) retry_wait=$2 ;;
--timeout) timeout=$2 ;;
--connect-timeout) connect_timeout=$2 ;;
esac
shift 2
;;
--connections=*|--retries=*|--retry-wait=*|--timeout=*|--connect-timeout=*)
local opt=${1%%=*} val=${1#*=}
_is_uint "$val" || _die "$opt requires a non-negative integer"
case "$opt" in
--connections) connections=$val ;;
--retries) retries=$val ;;
--retry-wait) retry_wait=$val ;;
--timeout) timeout=$val ;;
--connect-timeout) connect_timeout=$val ;;
esac
shift
;;
-h|--help)
cat <<'EOF_HELP'
Usage: dlwrap [OPTIONS] -- COMMAND [ARG...]
Run COMMAND with curl/wget intercepted and simple file downloads translated
into aria2c. Unsupported invocations fall back to the original downloader.
Options:
-p, --progress force progress output, overriding curl -s / wget -q
-v, --verbose force verbose downloader output (implies --progress)
--stream preserve native streaming for stdout downloads
--connections N aria2 connections/splits per download (default: 16)
--retries N aria2 max tries (default: 10)
--retry-wait SEC delay between retries (default: 2)
--timeout SEC socket timeout (default: 30)
--connect-timeout SEC
connection-establishment timeout (default: 10)
-h, --help show this help
Environment variables with matching DLWRAP_* names may also set defaults.
EOF_HELP
exit 0
;;
--) shift; break ;;
*) _die "unknown option '$1' (COMMAND must follow --)" ;;
esac
done
[ $# -gt 0 ] || _die 'missing COMMAND after --'
[ -d "$shim_dir" ] || _die "shim directory not found: $shim_dir"
[ -x "$shim_dir/curl" ] || _die "curl shim not found: $shim_dir/curl"
[ -x "$shim_dir/wget" ] || _die "wget shim not found: $shim_dir/wget"
local aria real_curl real_wget
aria=$(_find_command_excluding aria2c "$shim_dir") || _die 'aria2c not found in PATH'
real_curl=$(_find_command_excluding curl "$shim_dir" || true)
real_wget=$(_find_command_excluding wget "$shim_dir" || true)
export DLWRAP_FORCE_PROGRESS=$progress
export DLWRAP_VERBOSE=$verbose
export DLWRAP_STREAM=$stream
export DLWRAP_CONNECTIONS=$connections
export DLWRAP_RETRIES=$retries
export DLWRAP_RETRY_WAIT=$retry_wait
export DLWRAP_TIMEOUT=$timeout
export DLWRAP_CONNECT_TIMEOUT=$connect_timeout
export DLWRAP_ARIA2C=$aria
export DLWRAP_REAL_CURL=$real_curl
export DLWRAP_REAL_WGET=$real_wget
export DLWRAP_SHIM_DIR=$shim_dir
export PATH="$shim_dir:$PATH"
exec "$@"
}
case "$prog" in
curl) _shim_curl "$@" ;;
wget) _shim_wget "$@" ;;
*) _dlwrap_main "$@" ;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment