Last active
July 17, 2020 05:42
-
-
Save alganet/140c7c12d1603c244a01 to your computer and use it in GitHub Desktop.
Serve any folder as a web server with $ curl -L http://tinyurl.com/servesh1 | sh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env sh | |
# serve.sh | |
# Modular version: https://gist.github.com/alganet/a22a1373dcee7c175d1e | |
# Expansion on zsh | |
command -v setopt 2>&1 >/dev/null && setopt SH_WORD_SPLIT | |
# POSIX on bash | |
export POSIXLY_CORRECT=1 | |
# Lists files and folders as HTML | |
# Uses a root directory $1 and relative directory $2 | |
lshtml () | |
{ | |
rootdir="${1}" | |
reldir="${2}" | |
target="${rootdir}/${reldir}" | |
target="${target%*/}" | |
lshtml_header "${reldir}" "${target}" | |
lshtml_item "${reldir}" "${target}" | |
lshtml_footer "${reldir}" "${target}" | |
} | |
lshtml_cat () ( cat "$@" ) | |
lshtml_item () | |
{ | |
reldir="${1}" | |
target="${2}" | |
if [ -d "${target}" ]; then | |
lshtml_dir "${reldir}" ${target} | |
elif [ -f "${target}" ]; then | |
lshtml_file "${reldir}" ${target} | |
fi | |
} | |
lshtml_file () | |
{ | |
reldir="${1}" | |
target="${2}" | |
lshtml_cat "${target}" | |
} | |
lshtml_dir () | |
{ | |
reldir="${1}" | |
target="${2}" | |
for file in ${target}/*; do | |
lshtml_diritem "${reldir}" "${file}" | |
done | |
} | |
lshtml_diritem () | |
{ | |
reldir="${1}" | |
file="${2}" | |
filepath="${reldir}$(basename "${file}")" | |
if [ -d "${file}" ]; then | |
filepath="${filepath}/" | |
fi | |
lshtml_link "${filepath}" | |
} | |
lshtml_link () | |
{ | |
filepath="${1}" | |
echo "<li><a href='${filepath}'>${filepath}</a></li>" | |
} | |
lshtml_header () | |
{ | |
CR="$(printf '\r')" | |
reldir="${1}" | |
target="${2}" | |
lshtml_cat <<-MSG | |
HTTP/1.1 200 OK | |
Connection: close | |
Content-Type: text/html | |
${CR} | |
MSG | |
} | |
lshtml_footer () | |
{ | |
CR="$(printf '\r')" | |
lshtml_cat <<-MSG | |
${CR} | |
${CR} | |
MSG | |
} | |
# Listens once to a HTTP request | |
# Calls $1 with CGI env vars, uses $2 for connection | |
# and $3 for buffer. | |
# Depends on cgirequest.sh | |
httpserver () | |
{ | |
callback="${1}" | |
fall="$(httpserver_netcat 8080 10)" | |
connector="${2:-$fall}" | |
buffer="${3}" | |
httpserver_export "${callback}" | |
${connector} < "${buffer}" | httpserver_cgi "${callback}" > "${buffer}" | |
} | |
httpserver_export () | |
{ | |
export SERVER_SOFTWARE="Mosai HTTP/1.0" | |
export SERVER_NAME="localhost" | |
export SERVER_PORT="8080" | |
export GATEWAY_INTERFACE="CGI/1.1" | |
export SCRIPT_NAME="${callback}" | |
export REMOTE_ADDR="127.0.0.1" | |
} | |
httpserver_netcat () ( echo "nc -l $1 $2" ) | |
httpserver_cgi () ( cgirequest "$@" ) | |
# Listens to httpserver using a temporary buffer | |
# Calls $1 with CGI env vars, uses $2 for connection. | |
# Depends on fifobuffer.sh, httpserver.sh, trap, mktemp and rm | |
httpfifo () | |
{ | |
callback="${1}" | |
buffer_dir="$(httpfifo_mktemp -d -t "XXXhtml")" | |
connector="${2}" | |
buffer=$(httpfifo_buffer "${buffer_dir}") | |
httpfifo_start "${buffer_dir}" | |
httpfifo_listen "${callback}" "${connector}" "${buffer}" | |
httpfifo_end "${buffer_dir}" | |
exit | |
} | |
httpfifo_mktemp () ( mktemp "$@" ) | |
httpfifo_buffer () ( fifobuffer "$@" ) | |
httpfifo_httpserver () ( httpserver "$@" ) | |
httpfifo_end () ( rm -rf "${1}" ) | |
httpfifo_start () ( trap 'httpfifo_abort "${1}"' 2 ) | |
httpfifo_listen () | |
{ | |
while true; do | |
httpfifo_httpserver "$@" | |
done | |
} | |
httpfifo_abort () | |
{ | |
buffer_dir="${1}" | |
rm -rf "${buffer_dir}" | |
echo "Bye!" 1>&2 | |
exit | |
} | |
# Creates a fifo buffer in a ${1} dir | |
# Depends on od, tr and mkfifo | |
fifobuffer () | |
{ | |
buffer_dir="${1}" | |
buffer_name="$(fifobuffer_random | fifobuffer_filename)" | |
buffer_file="${buffer_dir}/${buffer_name}" | |
fifobuffer_mkfifo "${buffer_file}" | |
echo "${buffer_file}" | |
} | |
fifobuffer_filename () ( tr " " "-" | tr -d '\n' ) | |
fifobuffer_random () ( od -N4 -tu /dev/random ) | |
fifobuffer_mkfifo () ( mkfifo "$@" ) | |
# Parses a HTTP message from stdin. | |
# Calls ${1} with CGI env vars. | |
# Depends on httpserver.sh, cut, tr and sed | |
cgirequest () | |
{ | |
cgirequest_callback "${1:-cat}" | |
} | |
cgirequest_callback () | |
{ | |
export SELF="${1}" | |
export REQUEST_METHOD="" | |
export REQUEST_URI="" | |
export SERVER_PROTOCOL="" | |
export REQUEST_DATA="" | |
export QUERY_STRING="" | |
export PATH_INFO="" | |
read -r REQUEST_METHOD REQUEST_URI SERVER_PROTOCOL | |
QUERY_STRING="$(echo "$REQUEST_URI" | cut -d "?" -f2-)" | |
PATH_INFO="$(echo "$REQUEST_URI" | cut -d "?" -f1)" | |
cgirequest_headers | |
cgirequest_data | |
httpserver_export "${SELF}" | |
${SELF} | |
} | |
cgirequest_headerspec () | |
{ | |
echo "${1}" | cut -d":" -f1 | tr 'a-z' 'A-Z' | tr '-' '_' | |
} | |
cgirequest_headerval () | |
{ | |
echo "${1}" | cut -d":" -f2 | tr -d '\r' | tr -d '\n' |\ | |
sed -e 's/^ *//' -e 's/ *$//' | |
} | |
cgirequest_headers () | |
{ | |
CR="$(printf '\r')" | |
header="" | |
while read -r header && [ ! "${header}" = "${CR}" ]; do | |
spec="$(cgirequest_headerspec "${header}")" | |
val="$(cgirequest_headerval "${header}")" | |
export "HTTP_${spec}=${val}" | |
done | |
} | |
cgirequest_data () | |
{ | |
request="" | |
if [ ! -z "${HTTP_CONTENT_LENGTH}" ]; then | |
read -n $HTTP_CONTENT_LENGTH request | |
fi | |
export REQUEST_DATA="${request}" | |
} | |
cgirequest_ok () | |
{ | |
CR="$(printf '\r')" | |
cat <<-MSG | |
HTTP/1.1 200 OK | |
Connection: close | |
Content-Type: text/html | |
${CR} | |
200 OK | |
MSG | |
} | |
myapplication () | |
{ | |
# lshtml lists folders and files as HTML | |
lshtml ${PWD} ${REQUEST_URI} | |
# show POST data | |
#echo ${REQUEST_DATA} | |
# headers as CGI env vars | |
#echo ${HTTP_ACCEPT} | |
} | |
# Listen to netcat connector (use 127.0.0.1:8081 on busybox) | |
httpfifo myapplication "nc -vl 127.0.0.1 ${1:-9999}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment