There is no standard Posix utility for making HTTP request, but:
- BSD
curl
is available on MacOS -
GNU
wget
is almost always the default on Linux
(and GNUcurl
is usually available) - BSD
curl.exe
is the default on Windows
In light of that, here are two Posix functions that you can reliably use on just about any Posixish operating system:
- Safe for command or
source
d function use (variables are namespaced with prefixes) - Runs in “strict mode” (clean exit on error)
shellcheck
-linted (Posix-compliant, no bashisms)
Plain http_get
- Safe for batch mode (silences progress bar)
- Safe for partial & resumable downloads (prefers
wget
when available) - Safe for
source
ing (variables are in subshell, and namespaced)
#!/bin/sh
## Usage: http_get <url> [filepath]
## Copyright (C) 2022 AJ ONeal <aj@therootcompany.com>
## Permission to copy and modify is granted under the CC0-1.0 license
set -e
set -u
http_get() { (
http_get_url="${1}"
http_get_filepath="${2:-"$(basename "${http_get_url}")"}"
if [ -z "${http_get_url}" ]; then
echo >&2 "Usage: http_get <url> [filepath]"
return 1
fi
if command -v wget > /dev/null; then
# wget supports resumable downloads
if ! wget -q -c "${http_get_url}" -O "${http_get_filepath}.part"; then
echo >&2 "failed to download ${http_get_url} to ${http_get_filepath}.part"
return 1
fi
elif command -v curl > /dev/null; then
if ! curl -fsSL "${http_get_url}" -o "${http_get_filepath}.part"; then
echo >&2 "failed to download ${http_get_url} to ${http_get_filepath}.part"
return 1
fi
fi
# move downloaded file into file location
mv "${http_get_filepath}.part" "${http_get_filepath}"
); }
http_get "${1:-}" "${2:-}"
Enhanced http_get
- Shows progress in interactive shells
#!/bin/sh
## Usage: http_get <url> [filepath]
## Copyright (C) 2022 AJ ONeal <aj@therootcompany.com>
## Permission to copy and modify is granted under the CC0-1.0 license
set -e
set -u
http_get() { (
http_get_url="${1}"
http_get_filepath="${2:-"$(basename "${http_get_url}")"}"
if [ -z "${http_get_url}" ]; then
echo >&2 "Usage: http_get <url> [filepath]"
return 1
fi
http_get__is_interactive_shell() {
# $- shows shell flags (error,unset,interactive,etc)
case $- in
*i*)
# true
return 0
;;
*)
# false
return 1
;;
esac
}
if command -v wget > /dev/null; then
http_get_show_progress=""
if http_get__is_interactive_shell; then
http_get_show_progress="--show-progress"
fi
# wget supports resumable downloads
if ! wget -q $http_get_show_progress -c "${http_get_url}" -O "${http_get_filepath}.part"; then
echo >&2 "failed to download ${http_get_url} to ${http_get_filepath}.part"
return 1
fi
elif command -v curl > /dev/null; then
# Silencing by default since even curl's progress bar has an interactive-only percent counter
# ¯\_(ツ)_/¯
http_get_show_progress="-s"
if http_get__is_interactive_shell; then
# for progress bar (rather than full stats)
http_get_show_progress="-#"
fi
# shellcheck disable=SC2086
# we want the flags to be split
if ! curl $http_get_show_progress -fSL "${http_get_url}" -o "${http_get_filepath}.part"; then
echo >&2 "failed to download ${http_get_url} to ${http_get_filepath}.part"
return 1
fi
fi
# move downloaded file into file location
mv "${http_get_filepath}.part" "${http_get_filepath}"
); }
http_get "${1:-}" "${2:-}"
License
Public Domain via the Creative Commons Zero license
(attribution appreciated)
http_get - A Posix-compliant function for HTTP Requests
Written in 2022 by AJ ONeal <aj@therootcompany.com>
To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
You should have received a copy of the CC0 Public Domain Dedication along with
this software. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.