2014-10-19 4 views
3

Docker 컨테이너의 경우 한 줄로 nc를 사용하는 최소 REST 웹 서버를 찾고있었습니다. 예를 들면 : 나는 질문 "Minimal web server using netcat"보고 있었다, 그러나 쉘 스크립트에 대한 호출을 프록시합니다netcat nc를 사용하여 최소한의 REST 웹 서버 만들기

* http://localhost/echo/marcello: prints marcello 
* http://localhost/date: prints the server's date 
* http://localhost/...: others 

... 난 그냥 다른 솔루션을 게시

while true ; do nc -l -p 1500 -c 'echo -e "HTTP/1.1 200 OK\n\n $(date)"'; done 

것과 같은 하나 라이너가 필요합니다 파일에서 길고로드됩니다 ...

답변

10

"https://stackoverflow.com/a/24342101/433814"에 @syme에서 ​​주어진 예제를 해킹하고 one-liner REST 서버를 만들었습니다. 일부 헤더가 누락되었지만 HTTP GET 및 구현되지 않은 리소스 404가 올바르게 처리됩니다.

  • /에코/{이름}

반환 주어진 :

rm -f out ; mkfifo out ; trap "rm -f out" EXIT ; while true ; do cat out | nc -l 1500 > >(export REQUEST= ; while read line ; do line=$(echo "$line" | tr -d '[\r\n]') ; if echo "$line" | grep -qE '^GET /' ; then REQUEST=$(echo "$line" | cut -d ' ' -f2) ; elif [ "x$line" = x ] ; then HTTP_200="HTTP/1.1 200 OK" ; HTTP_LOCATION="Location:" ; HTTP_404="HTTP/1.1 404 Not Found" ; if echo $REQUEST | grep -qE '^/echo/' ; then printf "%s\n%s %s\n\n%s\n" "$HTTP_200" "$HTTP_LOCATION" $REQUEST ${REQUEST#"/echo/"} > out ; elif echo $REQUEST | grep -qE '^/date' ; then date > out ; elif echo $REQUEST | grep -qE '^/stats' ; then vmstat -S M > out ; elif echo $REQUEST | grep -qE '^/net' ; then ifconfig > out ; else printf "%s\n%s %s\n\n%s\n" "$HTTP_404" "$HTTP_LOCATION" $REQUEST "Resource $REQUEST NOT FOUND!" > out ; fi ; fi ; done) ; done 

포맷 된 버전이 https://gist.github.com/marcellodesales/9e4288f35ac2cc3e1b83#file-formatted

에 위치한 API 위 다음을 구현 {name}

$ curl -i http://localhost:1500/echo/marcello 
HTTP/1.1 200 OK 
Location: /echo/marcello 

marcello 

반환 날짜/서버의 날짜

$ curl -i http://localhost:1500/date 
Sun Oct 19 14:12:27 PDT 2014 
  • /통계

는 서버의 통계

$ curl -i http://localhost:1500/stats 
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- 
r b swpd free buff cache si so bi bo in cs us sy id wa st 
0 0  11 374 383 2198 0 0  6 22 33 8 2 2 97 0 0 
  • /순

인쇄 서버의 네트워크

$ curl -i http://localhost:1500/net 
docker0 Link encap:Ethernet HWaddr 56:84:7a:fe:97:99 
      inet addr:172.17.42.1 Bcast:0.0.0.0 Mask:255.255.0.0 
      inet6 addr: fe80::5484:7aff:fefe:9799/64 Scope:Link 
      UP BROADCAST MULTICAST MTU:1500 Metric:1 
      RX packets:120694 errors:0 dropped:0 overruns:0 frame:0 
      TX packets:141757 errors:0 dropped:0 overruns:0 carrier:0 
      collisions:0 txqueuelen:0 
      RX bytes:272911625 (272.9 MB) TX bytes:289945068 (289.9 MB) 

eth0  Link encap:Ethernet HWaddr 00:0c:29:1f:d3:b5 
      inet addr:192.168.248.206 Bcast:192.168.248.255 Mask:255.255.255.0 
      inet6 addr: fe80::20c:29ff:fe1f:d3b5/64 Scope:Link 
      UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 
      RX packets:2322493 errors:0 dropped:0 overruns:0 frame:0 
      TX packets:1098965 errors:0 dropped:0 overruns:0 carrier:0 
      collisions:0 txqueuelen:1000 
      RX bytes:2367412677 (2.3 GB) TX bytes:700548644 (700.5 MB) 

lo  Link encap:Local Loopback 
      inet addr:127.0.0.1 Mask:255.0.0.0 
      inet6 addr: ::1/128 Scope:Host 
      UP LOOPBACK RUNNING MTU:65536 Metric:1 
      RX packets:151566 errors:0 dropped:0 overruns:0 frame:0 
      TX packets:151566 errors:0 dropped:0 overruns:0 carrier:0 
      collisions:0 txqueuelen:0 
      RX bytes:305833574 (305.8 MB) TX bytes:305833574 (305.8 MB) 
    반환 6,
  • 은/아무거나는 NOT/서버가 구현하지 않습니다 아무것도 들어

구현은 404 메시지를 출력 /.

$ curl -i http://localhost:1500/wrong 
HTTP/1.1 404 Not Found 
Location: /wrong 

Resource /wrong NOT FOUND! 

위의 GIST의 형식화 된 솔루션은 다음과 같습니다. "웹"으로 저장할 수 있습니다.SH "실행 : netcat을 가진 강타의 또 다른 완전하고 간단한 해결책은 다음이 하나가

rm -f out 
mkfifo out 
trap "rm -f out" EXIT 
while true 
do 
    cat out | nc -l 1500 > >(# parse the netcat output, to build the answer redirected to the pipe "out". 
    export REQUEST= 
    while read line 
    do 
     line=$(echo "$line" | tr -d '[\r\n]') 

     if echo "$line" | grep -qE '^GET /' # if line starts with "GET /" 
     then 
     REQUEST=$(echo "$line" | cut -d ' ' -f2) # extract the request 
     elif [ "x$line" = x ] # empty line/end of request 
     then 
     HTTP_200="HTTP/1.1 200 OK" 
     HTTP_LOCATION="Location:" 
     HTTP_404="HTTP/1.1 404 Not Found" 
     # call a script here 
     # Note: REQUEST is exported, so the script can parse it (to answer 200/403/404 status code + content) 
     if echo $REQUEST | grep -qE '^/echo/' 
     then 
      printf "%s\n%s %s\n\n%s\n" "$HTTP_200" "$HTTP_LOCATION" $REQUEST ${REQUEST#"/echo/"} > out 
     elif echo $REQUEST | grep -qE '^/date' 
     then 
      date > out 
     elif echo $REQUEST | grep -qE '^/stats' 
     then 
      vmstat -S M > out 
     elif echo $REQUEST | grep -qE '^/net' 
     then 
      ifconfig > out 
     else 
      printf "%s\n%s %s\n\n%s\n" "$HTTP_404" "$HTTP_LOCATION" $REQUEST "Resource $REQUEST NOT FOUND!" > out 
     fi 
     fi 
    done 
) 
done 
+0

좋은 해킹을위한 잘 쓰여진 답변이지만, 1 마일 1/2 너비의 1 개의 라이너? 설명이 훌륭하게 구조화되어 있습니다. 코드가 아닌 이유는 무엇입니까? – shellter

+0

Thanks @shellter :) 링크 GIST는 답변에 나와 있습니다.)하지만 대답의 일부로 확실히 포함시킬 수 있습니다 ... 요구 사항에서 언급했듯이 가장 기본적인 Docker에서 실행할 수 있기를 원하기 때문에 저는 oneliner가 필요합니다. 컨테이너 : D를 하나의 라이너로 ... 비밀 번호 없음 :) –

+2

docker에 대해 많이 알지는 못하지만, crontab 항목과 비슷한 비슷한 작업을 수행했습니다. 업데이트 해 주셔서 감사 드리며, 무엇을하고 있는지 쉽게 볼 수 있습니다 ;-). 행운을 빕니다. – shellter

0

. 그것은 https://github.com/jdoleczek/Bash-NetCat-HTTPD/blob/master/httpd.sh

#!/bin/bash 
# LICENSE MIT 

PORT=${1:-8080} 
FILES=${2:-"./"} 

NS=$(netstat -taupen 2>/dev/null | grep ":$PORT ") 
test -n "$NS" && echo "Port $PORT is already taken" && exit 1 

echo -e "\n\tHTTPD started for files in $FILES:" 

for IP in $(ifconfig | grep "inet addr" | cut -d ':' -f 2 | cut -d ' ' -f 1) ; do 
    echo -e "\tlistening at $IP:$PORT" 
done 

echo -e "\n" 
FIFO="/tmp/httpd$PORT" 
rm -f $FIFO 
mkfifo $FIFO 
trap ctrl_c INT 

function ctrl_c() { 
    rm -f $FIFO && echo -e "\n\tServer shut down.\n" && exit 
} 

while true; do (
    read req < $FIFO; 
    req=$(echo $req | cut -d" " -f2 | cut -d"#" -f1 | cut -d"?" -f1 | cut -c2-); 
    >&2 echo -e -n "\tRequest: \"$req\"\t"; 
    test -z "$req" && req="index.html" 

    if [ -f "$FILES$req" ] ; then 
     ext="${req##*.}" 
     ext=$(echo "$ext" | tr '[:upper:]' '[:lower:]') 

     case "$ext" in 
      "html" | "htm") CONTENTTYPE="text/html; charset=UTF-8" ;; 
      "json") CONTENTTYPE="application/json; charset=UTF-8" ;; 
      "css" | "less" | "sass") CONTENTTYPE="text/css" ;; 
      "txt") CONTENTTYPE="text/plain" ;; 
      "xml") CONTENTTYPE="text/xml" ;; 
      "js") CONTENTTYPE="application/javascript" ;; 
      "jpg" | "jpeg") CONTENTTYPE="image/jpeg" ;; 
      "png") CONTENTTYPE="image/png" ;; 
      "gif") CONTENTTYPE="image/gif" ;; 
      "ico") CONTENTTYPE="image/x-icon" ;; 
      "wav") CONTENTTYPE="audio/wav" ;; 
      "mp3") CONTENTTYPE="audio/mpeg3" ;; 
      "avi") CONTENTTYPE="video/avi" ;; 
      "mp4" | "mpg" | "mpeg" | "mpe") CONTENTTYPE="video/mpeg" ;; 
      *) CONTENTTYPE="application/octet-stream" 
     esac 

     echo "HTTP/1.x 200 OK" 
     echo "Date: $(LC_TIME=en_US date -u)" 
     echo "Server: promyk.doleczek.pl" 
     echo "Connection: close" 
     echo "Pragma: public" 
     echo "Content-Type: $CONTENTTYPE" 
     FILESIZE=$(wc -c < "$FILES$req") 
     echo -e "Content-Length: $FILESIZE\n" 
     cat "$FILES$req" 
     >&2 echo "[ ok ]" 
    else 
     echo -e "HTTP/1.x 404 Not found\n\n<h1>File not found.</h1>" 
     >&2 echo "[ no file ]" 
    fi 
) | nc -l -k -w 1 -p $PORT > $FIFO; done; 
에서 확인할 수 있습니다 콘텐츠 형식, 파일 크기 및 훨씬 더. 최신 버전을 지원합니다