Skip to content

Instantly share code, notes, and snippets.

@wallentx
Last active February 12, 2024 20:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wallentx/3f49089fa32e084e29085f5208c6dead to your computer and use it in GitHub Desktop.
Save wallentx/3f49089fa32e084e29085f5208c6dead to your computer and use it in GitHub Desktop.
GNU URL
#!/bin/bash
# Initialize options
follow_redirects=false
show_headers_only=false
silence_output=false
# Process options
while getopts "LsI" opt; do
case $opt in
L)
follow_redirects=true
;;
s)
silence_output=true
;;
I)
show_headers_only=true
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 1
;;
esac
done
# Shift off the options and flags processed by getopts
shift $((OPTIND-1))
# Initial URL
url_input=$1
follow_redirect() {
local url="$1"
# Remove protocol part
local stripped_url="${url#http://}"
stripped_url="${stripped_url#https://}"
# Extract host and path
local host="${stripped_url%%/*}"
local path="${stripped_url#"$host"}"
path="${path:-/}" # Default path to '/' if empty
# Determine protocol and port
local protocol port
if [[ "$url" == https://* ]]; then
protocol="openssl s_client -quiet -ignore_unexpected_eof -connect"
port="443"
else
protocol="/dev/tcp"
port="80"
fi
# Make the request and capture the response
if [ "$protocol" == "/dev/tcp" ]; then
exec 3<>/dev/tcp/${host}/${port}
echo -e "GET ${path} HTTP/1.1\r\nHost: ${host}\r\nConnection: close\r\n\r\n" >&3
response=$(cat <&3)
else
response=$(echo -e "GET ${path} HTTP/1.1\r\nHost: ${host}\r\nConnection: close\r\n\r\n" | openssl s_client -quiet -ignore_unexpected_eof -connect "${host}:${port}" 2>/dev/null)
fi
# Parse status code and Location header
local status=$(echo "$response" | grep -oE "HTTP/1.1 [0-9]+" | awk '{print $2}')
local location=$(echo "$response" | grep -i "^Location:" | head -n 1 | cut -d' ' -f2)
# Strip carriage return from the location
location=$(echo "$location" | tr -d '\r')
if $silence_output && ! $show_headers_only; then
if [[ "$status" != "301" && "$status" != "302" ]]; then
echo "$response" | tr -d '\r' | sed -n '/^$/,$p' # Print response body only
fi
else
if $show_headers_only; then
echo "$response" | grep -P "^(HTTP/1.1|[A-Za-z-]+:)"
elif [[ "$status" == "301" || "$status" == "302" ]] && [ ! -z "$location" ]; then
echo "Following redirect to $location" >&2
follow_redirect "$location"
else
echo "$response"
fi
fi
}
follow_redirect "$url_input"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment