20070830

Веб-сервер в одну строчку: версия 2.1

Алексей Свешников опубликовал в своём блоге пример веб-сервера, занимающего одну строчку на bash. Очень меня этой безделушкой порадовал. Красиво!

Однако его «сервер» у меня не заработал :)

Если запрос слать телнетом, то вроде что-то шлёт в ответ, а если запрашивать браузером или wget — нет. Пишется: ««127.0.0.1» разорвал соединение».

У меня возникло подозрение, что это из-за того, что скрипт начинает отвечать, не дождавшись конца HTTP запроса (а должен читать заголовки запроса до пустой строки). Я это исправил и wget заработал.

Также, при выдаче каталога хорошо бы отдавать Content-Type, подумал я. Например, без верного Content-Type wget сохраняет пустой файл.

И честно говорить, что это HTTP/1.0. Или поставить HTTP/1.1 и добавить Connection: close. (HTTP/1.1 applications that do not support persistent connections MUST include the "close" connection option in every message. —RFC2616)

Потом ещё я увидел, что символы перевода строк где-то «защищаются» bash. А именно во время вывода echo. Приходят литералы «\n» вместо кодов CRLF. А положено, чтобы шли именно CRLF. И заголовок ответа также должен заканчиваться пустой строкой.

В общем, вот мой вариант (эта версия у меня работает и с браузером, и с wget):

true; while [ $? -eq 0 ];do nc -vlp 8080 -c'(r=read;e=echo;$r a b c;E=NOTYET;while [ ${#E} -gt 0 ];do $r E;E=`$e $E|tr -d "\r\n"`;done;f=`$e $b|sed 's/[^a-z0-9_.-]//gi'`;h="HTTP/1.0";o="$h 200 OK\r\n";c="Content";if [ -z $f ];then($e -e $o;ls|(while $r n;do if test -f ${n}; then $e "<a href=\"/$n\">$n</a><br>";fi;done););elif [ -f $f ];then $e -e "$o$c-Type: `file -ib $f`\n$c-Length: `stat -c%s $f`\n";cat $f;else $e -e "$h 404 Not Found\n\n404\n";fi)';done


Эта версия ещё и скрывает подкаталоги текущего каталога, показывая только файлы. Набирать одной строчкой и смотреть результаты на 127.0.0.1:8080.