シェルスクリプトでwebアプリケーションフレームワークを作ってみた
概要
なんとなく作り始めてみました。
セキュリティホールがいっぱいあると思われるので、ローカルホストの外に出しちゃダメね。
ざっくりとした仕様など
動作確認はFreeBSD 8.3でのみ実施。
最近Play Frameworkを使ってるので、だいたいそんなかんじ。
設計
- bin/start が bin/listen を無限ループで呼び出す
- bin/listen は、1回のリクエスト毎にリクエストヘッダを解析し、メソッド名とurlを引数にrouter.shを呼び出す
- router.sh はシェル内の記述に則り、controller(app/*.sh)を呼び出す
- controller(app/*.sh)はいろいろ処理した後、renderコマンドでhtml(app/html/*.html)を出力する
- renderコマンドにはレスポンスコード(OK|BAD_REQUEST)・コンテキストタイプ・出力するhtmlファイルのファイル名を渡す
ソースコード一部抜粋
<View>
app/html/index.html
<html> <head> <title>テスト</title> </head> <body> <p class="hoge">hello world</p> <p>`date`</p> </body> </html>
※出力はこうなります
<html> <head> <title>テスト</title> </head> <body> <p class="hoge">hello world</p> <p>2014年 1月16日 木曜日 03時22分14秒 JST</p> </body> </html>
<Controller>
app/index.sh
#!/bin/sh
render OK HTML index.html
lib/render
#!/bin/sh status=$1 content=$2 html=$3 cat lib/status/${status} cat lib/contenttype/${content} echo "" printf "cat <<++EOF\n`cat app/html/${html}` \n++EOF\n" | sh
<基盤>
router.sh
#!/bin/sh PATH=$PATH:lib method=$1 url=$2 case "${url}" in "/" | "/index.html") app/index.sh return $? ;; *) render BAD_REQUEST PLAIN error.txt return 9 ;; esac
bin/listen
#!/usr/local/bin/bash LISTEN_PORT=8080 function server() { # request IFS=' ' read -u ${FD} "method" "path" "protocol" # header # TODO:後で実装。awk使ったほうがいいかも。 declare -A HEADERS HEADERS[Host]="ServerName" ./router.sh "${method}" "${path}" # status if [ $? -eq 0 ] ; then echo "${HEADERS[Host]};`date`; ${method}; ${path}" >&2 else echo "process failed : ${HEADERS[Host]};`date`; ${method}; ${path}" >&2 fi unset HEADERS } PIPE_FILE=tmp/server.$$ if [ ! -e "${PIPE_FILE}" ]; then mkfifo "${PIPE_FILE}" fi exec {FD}<>"${PIPE_FILE}" trap "test -e ${PIPE_FILE} && rm -f ${PIPE_FILE};exit" 0 HUP INT QUIT server | nc -l ${LISTEN_PORT} >&${FD}
参考URL
- NetCatのwikipedia
- パラメータの読み込みなどについては、ここを参考にさせて頂きました