|
| 1 | +#!/usr/bin/env bash |
| 2 | + |
| 3 | +print_help() { |
| 4 | + cat <<'END' |
| 5 | +Usage: httpstat URL [CURL_OPTIONS] |
| 6 | + httpstat -h | --help |
| 7 | + httpstat --version |
| 8 | +Arguments: |
| 9 | + URL url to request, could be with or without `http(s)://` prefix |
| 10 | +Options: |
| 11 | + CURL_OPTIONS any curl supported options, except for -w -D -o -S -s, |
| 12 | + which are already used internally. |
| 13 | + -h --help show this screen. |
| 14 | + --version show version. |
| 15 | +Environments: |
| 16 | + HTTPSTAT_SHOW_BODY By default httpstat will write response body |
| 17 | + in a tempfile, but you can let it print out by setting |
| 18 | + this variable to `true`. |
| 19 | + HTTPSTAT_SHOW_SPEED set to `true` to show download and upload speed. |
| 20 | +END |
| 21 | +} |
| 22 | + |
| 23 | +green="\033[32m" |
| 24 | +cyan="\033[36m" |
| 25 | +white="\033[37m" |
| 26 | +reset="\033[0m" |
| 27 | + |
| 28 | +while (( $# > 0 )) |
| 29 | +do |
| 30 | + case "$1" in |
| 31 | + -h | --help) |
| 32 | + print_help |
| 33 | + exit 1 |
| 34 | + ;; |
| 35 | + --version) |
| 36 | + echo "httpstat 0.0.1" |
| 37 | + exit 0 |
| 38 | + ;; |
| 39 | + '-w' | '--write-out') |
| 40 | + continue |
| 41 | + ;; |
| 42 | + '-D' | '--dump-header') |
| 43 | + continue |
| 44 | + ;; |
| 45 | + '-o' | '--output') |
| 46 | + continue |
| 47 | + ;; |
| 48 | + '-s' | '--silent') |
| 49 | + continue |
| 50 | + ;; |
| 51 | + -* | --*) |
| 52 | + args+=( "$1" ) |
| 53 | + ;; |
| 54 | + *) |
| 55 | + url="$1" |
| 56 | + ;; |
| 57 | + esac |
| 58 | + shift |
| 59 | +done |
| 60 | + |
| 61 | +if [[ -z $url ]]; then |
| 62 | + echo "too few arguments" >&2 |
| 63 | + exit 1 |
| 64 | +fi |
| 65 | + |
| 66 | +curl_format='{ |
| 67 | +"time_namelookup": %{time_namelookup}, |
| 68 | +"time_connect": %{time_connect}, |
| 69 | +"time_appconnect": %{time_appconnect}, |
| 70 | +"time_pretransfer": %{time_pretransfer}, |
| 71 | +"time_redirect": %{time_redirect}, |
| 72 | +"time_starttransfer": %{time_starttransfer}, |
| 73 | +"time_total": %{time_total}, |
| 74 | +"speed_download": %{speed_download}, |
| 75 | +"speed_upload": %{speed_upload} |
| 76 | +}' |
| 77 | + |
| 78 | +head="/tmp/httpstat-header.$$$RANDOM$(date +%s)" |
| 79 | +body="/tmp/httpstat-body.$$$RANDOM$(date +%s)" |
| 80 | + |
| 81 | +data="$( |
| 82 | +LC_ALL=C curl \ |
| 83 | + -w "$curl_format" \ |
| 84 | + -D "$head" \ |
| 85 | + -o "$body" \ |
| 86 | + -s -S \ |
| 87 | + "${args[@]}" \ |
| 88 | + "$url" 2>&1 |
| 89 | +)" |
| 90 | + |
| 91 | +get() { |
| 92 | + local d |
| 93 | + d="$( |
| 94 | + echo "$data" \ |
| 95 | + | grep "$1" \ |
| 96 | + | awk '{print $2}' \ |
| 97 | + | sed 's/,//g' |
| 98 | + )" |
| 99 | + if type bc &>/dev/null; then |
| 100 | + echo "$d"*1000 | bc -l |
| 101 | + else |
| 102 | + echo "$d" | awk 'END{print $0*1000}' |
| 103 | + fi |
| 104 | +} |
| 105 | + |
| 106 | +calc() { |
| 107 | + if type bc &>/dev/null; then |
| 108 | + echo "$@" | bc -l |
| 109 | + else |
| 110 | + echo "$@" | awk "BEGIN{print $*}" |
| 111 | + fi |
| 112 | +} |
| 113 | + |
| 114 | +time_namelookup="$(get time_namelookup)" |
| 115 | +time_connect="$(get time_connect)" |
| 116 | +time_appconnect="$(get time_appconnect)" |
| 117 | +time_pretransfer="$(get time_pretransfer)" |
| 118 | +time_redirect="$(get time_redirect)" |
| 119 | +time_starttransfer="$(get time_starttransfer)" |
| 120 | +time_total="$(get time_total)" |
| 121 | +speed_download="$(get speed_download)" |
| 122 | +speed_upload="$(get speed_upload)" |
| 123 | + |
| 124 | +range_dns="$time_namelookup" |
| 125 | +range_connection="$(calc "$time_connect" - "$time_namelookup")" |
| 126 | +range_ssl="$(calc "$time_pretransfer" - "$time_connect")" |
| 127 | +range_server="$(calc "$time_starttransfer" - "$time_pretransfer")" |
| 128 | +range_transfer="$(calc "$time_total" - "$time_starttransfer")" |
| 129 | + |
| 130 | +fmta() { |
| 131 | + echo "$1" \ |
| 132 | + | awk '{printf("%5dms\n", $1 + 0.5)}' |
| 133 | +} |
| 134 | + |
| 135 | +fmtb() { |
| 136 | + local d |
| 137 | + d="$( |
| 138 | + echo "$1" \ |
| 139 | + | awk '{printf("%d\n", $1 + 0.5)}' |
| 140 | + )" |
| 141 | + printf "%-7s\n" "${d}ms" |
| 142 | +} |
| 143 | + |
| 144 | +a000="$cyan$(fmta "$range_dns")$reset" |
| 145 | +a001="$cyan$(fmta "$range_connection")$reset" |
| 146 | +a002="$cyan$(fmta "$range_ssl")$reset" |
| 147 | +a003="$cyan$(fmta "$range_server")$reset" |
| 148 | +a004="$cyan$(fmta "$range_transfer")$reset" |
| 149 | +b000="$cyan$(fmtb "$time_namelookup")$reset" |
| 150 | +b001="$cyan$(fmtb "$time_connect")$reset" |
| 151 | +b002="$cyan$(fmtb "$time_pretransfer")$reset" |
| 152 | +b003="$cyan$(fmtb "$time_starttransfer")$reset" |
| 153 | +b004="$cyan$(fmtb "$time_total")$reset" |
| 154 | + |
| 155 | +https_template="$white |
| 156 | + DNS Lookup TCP Connection SSL Handshake Server Processing Content Transfer$reset |
| 157 | +[ ${a000} | ${a001} | ${a002} | ${a003} | ${a004} ] |
| 158 | + | | | | | |
| 159 | + namelookup:${b000} | | | | |
| 160 | + connect:${b001} | | | |
| 161 | + pretransfer:${b002} | | |
| 162 | + starttransfer:${b003} | |
| 163 | + total:${b004} |
| 164 | +" |
| 165 | + |
| 166 | +http_template="$white |
| 167 | + DNS Lookup TCP Connection Server Processing Content Transfer$reset |
| 168 | +[ ${a000} | ${a001} | ${a003} | ${a004} ] |
| 169 | + | | | | |
| 170 | + namelookup:${b000} | | | |
| 171 | + connect:${b001} | | |
| 172 | + starttransfer:${b003} | |
| 173 | + total:${b004} |
| 174 | +" |
| 175 | + |
| 176 | +# output, need to print escape sequences raw (disable those checks for shellcheck) |
| 177 | +# shellcheck disable=SC2059,SC2002 |
| 178 | +{ |
| 179 | + # Print header |
| 180 | + cat "$head" \ |
| 181 | + | perl -pe 's/^(HTTP)(.*)$/'''"$green"'$1'''"$reset""$cyan"'$2'''"$reset"'/g' \ |
| 182 | + | perl -pe 's/^(.*?): (.*)$/'''"$white"'$1: '''"$cyan"'$2/g' |
| 183 | + printf "$reset" |
| 184 | + |
| 185 | + # Print body |
| 186 | + if [[ "$HTTPSTAT_SHOW_BODY" == true ]]; then |
| 187 | + cat "$body"; printf '\n' |
| 188 | + else |
| 189 | + printf "${green}Body${reset} stored in: $body\n" |
| 190 | + fi |
| 191 | + |
| 192 | + if [[ "$url" =~ https:// ]]; then |
| 193 | + printf "$https_template\n" |
| 194 | + else |
| 195 | + printf "$http_template\n" |
| 196 | + fi |
| 197 | + |
| 198 | + # speed, originally bytes per second |
| 199 | + if [[ "$HTTPSTAT_SHOW_SPEED" == true ]]; then |
| 200 | + printf "speed_download %.1f KiB, speed_upload %.1f KiB\n" \ |
| 201 | + "$(calc "$speed_download" / 1024)" \ |
| 202 | + "$(calc "$speed_upload" / 1024)" |
| 203 | + fi |
| 204 | +} |
0 commit comments