Webserver per Shellscript

Andy_m4

Well-Known Member
Wurde nur mit Shell Script und auf CLI gemacht
Na wenn, dann richtig und der Webserver muss auch ein Shellskript sein :-)
Bash:
#!/bin/sh

printHelptext() {
  echo "Usage: $0  <fifo> <port> [<bindaddress>]"
  echo "Serve Files from current directory"
  echo "Example:"
  echo "sh $0 /tmp/webserv.fifo 8099"
  echo ""
}

# Argumente prüfen: Es müssen genau 3 Argumente übergeben werden.
if [ "$#" -lt 2 ] || [ "$#" -gt 3 ]; then
  printHelptext
  exit 1
fi

FIFOFILE="$1"
PORT="$2"
BINDADDR="${3:-}"

## Create the response FIFO
rm -f "$FIFOFILE"
mkfifo "$FIFOFILE"

get_mime_type() {
  case "$1" in
    *.html) echo "text/html; charset=utf-8" ;;
    *.htm) echo "text/html" ;;
    *.txt) echo "text/plain" ;;
    *.css) echo "text/css" ;;
    *.js) echo "application/javascript" ;;
    *.json) echo "application/json" ;;
    *.png) echo "image/png" ;;
    *.jpg | *.jpeg) echo "image/jpeg" ;;
    *.gif) echo "image/gif" ;;
    *.svg) echo "image/svg+xml" ;;
    *.pdf) echo "application/pdf" ;;
    *) echo "application/octet-stream" ;; # Standard MIME-Typ für unbekannte Dateitypen
  esac
}

createResponse() {
   httpstatus="$1"
   mimetype="$2"
   lastmodified="$3"
   shift 3
   body="$@"
   response=""
   now="$(env LANG=C date +'%a, %d %b %Y %H:%M:%S %Z')"
   if [ -z "$lastmodified" ]; then
     lastmodified="$now"
   fi
   response="${response}HTTP/1.1 ${httpstatus}\r\n"
   response="${response}Content-Type: ${mimetype}\r\n"
   response="${response}Content-Length: ${#body}\r\n"
   response="${response}X-Robots-Tag: noarchive\r\n"
   response="${response}Date: ${now}\r\n"
   response="${response}Last-Modified: ${lastmodified}\r\n"
   response="${response}Connection: close\r\n"
   response="${response}\r\n"
   response="${response}${body}"
   echo -n "${response}"
}

handleRequest() {
  ## Lese HTPP-Request bis \r\n
  while read line; do
    trline=$(echo $line | tr -d '[\r\n]') ## Removes the \r\n from the EOL

    ## while-Schleife verlassen, wenn Leerzeile
    [ -z "$trline" ] && break

    # Parse Zeile der Anfrage
    if echo "$trline" | grep -q "^GET "; then
      # Extrahiere den Pfad
      request_path=$(echo "$trline" | awk '{print $2}')
      echo "request-path: $request_path" >&2
      # Entferne das führende '/'
      file_to_serve=${request_path#/}
      echo "file_to_serve: $file_to_serve" >&2
      if [ -n "$file_to_serve" ] && [ -f "$file_to_serve" ]; then
        # Datei gefunden, erstelle die HTTP-Antwort für reguläre Dateien
        mime_type=$(get_mime_type "$file_to_serve")
        RESPONSE="$(createResponse "200 OK" "$mime_type" "$(env LANG=C date -r "$(stat -f %m "$file_to_serve")" +'%a, %d %b %Y %H:%M:%S %Z')" "$(cat "$file_to_serve")")"
      else
        # Datei nicht gefunden
        RESPONSE="$(createResponse "404 Not Found" "text/plain" "" "404 Not Found\r\nPath: ${request_path}")"
      fi
    fi
  done
  echo "response: $RESPONSE" >&2
  echo -e "$RESPONSE" > "$FIFOFILE"
}

cleanup() {
  rm -f "$FIFOFILE"
  exit 0
}

trap cleanup SIGINT

echo "Link: http://${BINDADDR:-$(hostname)}:$PORT"

# Server-Loop
while true; do
  cat "$FIFOFILE" | nc -lN  ${BINDADDR:+$BINDADDR}  "$PORT" | handleRequest
done
 
Das gehoert nur wirklich nicht hier her..
Ok. :-)

Noch ein Hinweis:
Das Skript ist eher nur so zur Anschauung gedacht. Bitte verwendet das nicht in "the real world".
Erstens ist es etwas wacklig. Zweitens ist es auch sicherheitstechnisch problematisch und bietet z.B. keinen Schutz gegen Angriffe wie http://myserver/../etc/passwd
Wenns nur darum geht, schnell und unkompliziert Dateien zu verteilen oder so, dann ist miniserv ganz praktikabel, finde ich.
 
Zurück
Oben