netcat을 사용하는 최소 웹 서버


129

netcat (nc)을 사용하여 최소 웹 서버를 설정하려고합니다. 예를 들어 브라우저가 localhost : 1500을 호출 할 때 함수의 결과를 표시해야합니다 ( 아래 예에서는 날짜 이지만 결국 일부 데이터를 생성하는 파이썬 또는 c 프로그램이됩니다). 내 작은 netcat 웹 서버는 bash에서 while true 루프 여야합니다. 아마도 다음과 같이 간단합니다.

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

이것을 시도하면 브라우저는 nc가 시작되는 순간 현재 사용 가능한 데이터를 보여줍니다. 그래도 브라우저가 요청하는 동안 브라우저가 데이터를 표시하고 싶습니다. 이것을 어떻게 할 수 있습니까?


저를 더 많은 인터넷 검색으로 이끄는 제안에 모두 감사드립니다. 그것이 일어 났을 때 나는 link 에서 완전히 다른 해결책을 발견했습니다 . 파이썬이나 C를 사용할 수 없지만 이미 모든 대상 플랫폼에서 테스트했습니다. netcat의 문제점은 주변에 너무 많은 버전이 있다는 것입니다. 그들 중 일부는 -e, -c 또는 -q 옵션을 허용하지 않습니다.
andwagon 2013 년

답변:


52

이 시도:

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

-c당신이 에코 사용할 수 있도록 만든다은 쉘에 주어진 명령을 실행 netcat을. 에코가 필요하지 않으면 -e. 이에 대한 자세한 내용을 보려면를 시도하십시오 man nc. 를 사용할 때 echo프로그램 ( date대체)이 브라우저 요청을받을 수있는 방법이 없습니다 . 따라서 마침내 다음과 같이하고 싶을 것입니다.

while true ; do nc -l -p 1500 -e /path/to/yourprogram ; done

yourprogramGET 처리, HTTP 200 전송 등과 같은 프로토콜 작업은 어디에서 해야합니까?


33
오픈 BSD netcat을 다른 작동, 당신은 같은 것을 할 수while true; do echo -e "HTTP/1.1 200 OK\n\n $(date)" | nc -l localhost 1500; done
matlehmann

2
에서 노스 캐롤라이나에 대한 사람 , -p 설명 :It is an error to use this option in conjunction with the -l option
sbeliakov

1
-l -p 조합은 질문에서 비롯되며 질문 작성자에게 적합한 것으로 보입니다. 그래서 나는 그것을 의심하지 않고 그것을 사용했습니다.
Constantin Berhard

2
내가 본 nc 맨 페이지에서도 -p옵션과 함께 옵션을 사용하는 -l것은 오류 라고 말하고 있지만 공식 netcat 웹 사이트는 예제에서 두 옵션을 모두 사용합니다. 참조 : nc110.sourceforge.net
LS

2
적어도 3 대의 "맛"이 있습니다 nc: 호빗 (원본), BSD / 맥 OS X , 그리고 GNU (무리의 가장 오래된, 그리고 더 이상 유지가). Nmap의 Ncat도 있습니다. 나는 그것의 가치는 것을주의 생각하기 때문에 나는이 위로를 가져다 -l-p플래그 함께 단지의 오류로 간주된다 BSD 맛 때문에 대체 구문은 @matlehmann에 의해 주어진, 노스 캐롤라이나의
마크 G.을

39

방법 또는 이유가 없지만 주변에서 이것을 찾을 수 있고 나를 위해 작동합니다. bash 실행 결과를 반환하고 싶었던 문제가있었습니다.

$ while true; do { echo -e 'HTTP/1.1 200 OK\r\n'; sh test; } | nc -l 8080; done

참고 : 이 명령은 http://www.razvantudorica.com/08/web-server-in-one-line-of-bash 에서 가져 왔습니다.

이것은 bash 스크립트 테스트를 실행하고 포트 8080에서이 명령을 실행하는 서버에 연결하는 브라우저 클라이언트에 결과를 반환합니다.

내 스크립트는이 ATM을 수행합니다.

$ nano test

#!/bin/bash

echo "************PRINT SOME TEXT***************\n"
echo "Hello World!!!"
echo "\n"

echo "Resources:"
vmstat -S M
echo "\n"

echo "Addresses:"
echo "$(ifconfig)"
echo "\n"


echo "$(gpio readall)"

내 웹 브라우저에

************PRINT SOME TEXT***************

Hello World!!!


Resources:
procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa
 0  0      0    314     18     78    0    0     2     1  306   31  0  0 100  0


Addresses:
eth0      Link encap:Ethernet  HWaddr b8:27:eb:86:e8:c5  
          inet addr:192.168.1.83  Bcast:192.168.1.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:27734 errors:0 dropped:0 overruns:0 frame:0
          TX packets:26393 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:1924720 (1.8 MiB)  TX bytes:3841998 (3.6 MiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)


GPIOs:
+----------+-Rev2-+------+--------+------+-------+
| wiringPi | GPIO | Phys | Name   | Mode | Value |
+----------+------+------+--------+------+-------+
|      0   |  17  |  11  | GPIO 0 | IN   | Low   |
|      1   |  18  |  12  | GPIO 1 | IN   | Low   |
|      2   |  27  |  13  | GPIO 2 | IN   | Low   |
|      3   |  22  |  15  | GPIO 3 | IN   | Low   |
|      4   |  23  |  16  | GPIO 4 | IN   | Low   |
|      5   |  24  |  18  | GPIO 5 | IN   | Low   |
|      6   |  25  |  22  | GPIO 6 | IN   | Low   |
|      7   |   4  |   7  | GPIO 7 | IN   | Low   |
|      8   |   2  |   3  | SDA    | IN   | High  |
|      9   |   3  |   5  | SCL    | IN   | High  |
|     10   |   8  |  24  | CE0    | IN   | Low   |
|     11   |   7  |  26  | CE1    | IN   | Low   |
|     12   |  10  |  19  | MOSI   | IN   | Low   |
|     13   |   9  |  21  | MISO   | IN   | Low   |
|     14   |  11  |  23  | SCLK   | IN   | Low   |
|     15   |  14  |   8  | TxD    | ALT0 | High  |
|     16   |  15  |  10  | RxD    | ALT0 | High  |
|     17   |  28  |   3  | GPIO 8 | ALT2 | Low   |
|     18   |  29  |   4  | GPIO 9 | ALT2 | Low   |
|     19   |  30  |   5  | GPIO10 | ALT2 | Low   |
|     20   |  31  |   6  | GPIO11 | ALT2 | Low   |
+----------+------+------+--------+------+-------+

단순히 놀랍습니다!


2
http 1.1은 연결을 추가하기 때문에 http 1.0을 사용하는 것이 좋습니다.이 경우에는 연결 유지가 좋지 않습니다.
Shimon Doodkin 2014 년

3
@ShimonDoodkin netcat은 HTTP를 이해하지 못하기 때문에 의미가 없습니다. 요청 헤더 -k에 추가 Connection: keep-alive하는 것이 아니라 플래그 를 전달하여 netcat에서 연결 유지를 활성화합니다 .
Braden Best

1
:)뿐만 아니라 Mac에서 이상한 NC 버전에서 작동합니다
judepereira

28

추가 -q 1받는 netcat명령 행 :

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

3
-q1에서 작동하지 않는 경우 CentOS에 사용되어야 하는지를 6.x에서 CentOS이 말을 어디 6.x의 : nc: invalid option -- 'q'. while true; do tail -f /usr/local/freeswitch/log/freeswitch.log | nc -l 9999; done &

@YumYumYum 저는 OS X에 있고 freeswitch가 없습니다. 내용은 /usr/local/freeswitch/log/freeswitch.log무엇입니까?
HairOfTheDog

3
추가 -q 1는 Ubuntu 18.04에서 나를 위해 일했습니다. 도움이되기를 바랍니다.
EmpathicSage

20

당신이 직면 한 문제는 nc가 웹 클라이언트가 요청에 응답 할 수 있도록 웹 클라이언트가 언제 완료되었는지 알지 못한다는 것입니다.
웹 세션은 다음과 같이 진행되어야합니다.

TCP session is established.
Browser Request Header: GET / HTTP/1.1
Browser Request Header: Host: www.google.com
Browser Request Header: \n #Note: Browser is telling Webserver that the request header is complete.
Server Response Header: HTTP/1.1 200 OK
Server Response Header: Content-Type: text/html
Server Response Header: Content-Length: 24
Server Response Header: \n #Note: Webserver is telling browser that response header is complete 
Server Message Body: <html>sample html</html>
Server Message Body: \n #Note: Webserver is telling the browser that the requested resource is finished. 
The server closes the TCP session.

"\ n"으로 시작하는 줄은 공백없이 단순히 빈 줄이며 줄 바꿈 문자 만 포함합니다.

xinetd, xinetd tutorial에 의해 시작된 bash httpd가 있습니다 . 또한 날짜, 시간, 브라우저 IP 주소 및 전체 브라우저 요청을 로그 파일에 기록하고 서버 헤더 응답에 대한 콘텐츠 길이를 계산합니다.

user@machine:/usr/local/bin# cat ./bash_httpd
#!/bin/bash
x=0;
Log=$( echo -n "["$(date "+%F %T %Z")"] $REMOTE_HOST ")$(
        while read I[$x] && [ ${#I[$x]} -gt 1 ];do
              echo -n '"'${I[$x]} | sed -e's,.$,",'; let "x = $x + 1";
        done ;
); echo $Log >> /var/log/bash_httpd

Message_Body=$(echo -en '<html>Sample html</html>')
echo -en "HTTP/1.0 200 OK\nContent-Type: text/html\nContent-Length: ${#Message_Body}\n\n$Message_Body"

더 많은 기능을 추가하려면 통합 할 수 있습니다.

            METHOD=$(echo ${I[0]} |cut -d" " -f1)
            REQUEST=$(echo ${I[0]} |cut -d" " -f2)
            HTTP_VERSION=$(echo ${I[0]} |cut -d" " -f3)
            If METHOD = "GET" ]; then 
                case "$REQUEST" in

                    "/") Message_Body="HTML formatted home page stuff"
                        ;;
                    /who) Message_Body="HTML formatted results of who"
                        ;;
                    /ps) Message_Body="HTML formatted results of ps"
                        ;;
                    *) Message_Body= "Error Page not found header and content"
                       ;;
                esac

            fi

해피 배싱!


11

나는 똑같은 필요 / 문제가 있었지만 여기서는 나를 위해 일하지 않았거나 (또는 ​​모든 것을 이해하지 못했습니다) 이것이 내 해결책입니다.

내 minimal_http_server.sh를 게시합니다 (내 / bin / bash (4.3.11)와 함께 작동하지만 리디렉션으로 인해 / bin / sh는 아님).

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 -r 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 [ -z "$line" ] # empty line / end of request
      then
        # call a script here
        # Note: REQUEST is exported, so the script can parse it (to answer 200/403/404 status code + content)
        ./a_script.sh > out
      fi
    done
  )
done

그리고 내 a_script.sh (필요에 따라) :

#!/bin/bash

echo -e "HTTP/1.1 200 OK\r"
echo "Content-type: text/html"
echo

date

minimal_http_server.sh를 실행 한 후 1 초 이내에 URL을 여러 번 쿼리하면 찾을 수없는 페이지가 표시됩니다. 그러나 각 요청에 대해 1 초 간격을 주면 제대로 작동합니다. 또한이 서비스를 계속 실행하고 다른 쉘 스크립트에서 curl 요청을 받으면 서비스가 중단되거나 충돌합니다. 잘못 될 수 있습니다 어떤 생각
사티 존

@satishjohn 현재의 기술 (당시보다 낫다)에서 방금 두 가지 주요 결함 ( readtr)과 사소한 결함 ( [elif 이후)을 수정했습니다. 나는 당신의 문제를 재현하지 않습니다. minimal_http_server.sh가 왜 이러한 1 초 간격을 유발하는지 알 수 없습니다. REQUEST 환경 변수를 설정 한 후 여러 번 (컬 요청과 동일한 속도로) ./a_script.sh를 실행하여 결함이있는 것이 minimal_http_server.sh인지 "a_script.sh"인지 판별 할 수 있습니다.
syme

11

이를 수행하는 또 다른 방법

while true; do (echo -e 'HTTP/1.1 200 OK\r\n'; echo -e "\n\tMy website has date function" ; echo -e "\t$(date)\n") | nc -lp 8080; done

curl을 사용하여 2 개의 HTTP 요청으로 테스트 해 보겠습니다.

이 예에서 172.16.2.6은 서버 IP 주소입니다.

서버 측

admin@server:~$ while true; do (echo -e 'HTTP/1.1 200 OK\r\n'; echo -e "\n\tMy website has date function" ; echo -e "\t$(date)\n") | nc -lp 8080; done

GET / HTTP/1.1 Host: 172.16.2.6:8080 User-Agent: curl/7.48.0 Accept:
*/*

GET / HTTP/1.1 Host: 172.16.2.6:8080 User-Agent: curl/7.48.0 Accept:
*/*

고객 입장에서

user@client:~$ curl 172.16.2.6:8080

        My website has date function
        Tue Jun 13 18:00:19 UTC 2017

user@client:~$ curl 172.16.2.6:8080

        My website has date function
        Tue Jun 13 18:00:24 UTC 2017

user@client:~$

다른 명령을 실행하려면 $ (date)를 자유롭게 바꾸십시오.


6
mkfifo pipe;
while true ; 
do 
   #use read line from pipe to make it blocks before request comes in,
   #this is the key.
   { read line<pipe;echo -e "HTTP/1.1 200 OK\r\n";echo $(date);
   }  | nc -l -q 0 -p 8080 > pipe;  

done

어떻게 작동합니까? read line<pipenc쓸 때까지 기다립니다 pipe? 하지만이 시점에서는 응답이 작성되기 전에 요청이 완료되었다고 생각합니다 ..?
fentas

mkfifo는 차단 파이프를 생성합니다. 즉, nc가 요청을 읽을 때까지 echo 명령이 실행되지 않습니다.
InvisibleWolf

5

여기의 아름다움을 조금 bash는 웹 서버가 그것을 사용하는 -, 나는 온라인을 발견하고 사본을 포크와 조금 그것을 깔끔하게 socat또는 netcat내가 그것을 테스트 한 socat- 그것은 독립적 인 하나의 스크립트에 자체 구성 파일을 생성 그리고 파비콘.

기본적으로 웹 지원 파일 브라우저로 시작되지만 모든 로직에 대한 구성 파일로 쉽게 구성됩니다. 파일의 경우 이미지와 음악 (mp3), 비디오 (mp4, avi 등)를 스트리밍합니다. 다양한 파일 형식을 스마트 워치를 포함한 Linux, Windows 및 Android 장치로 스트리밍하는 것을 테스트했습니다!

실제로 VLC보다 더 잘 스트리밍한다고 생각합니다. USB 포트에 물리적으로 연결하는 것에 대해 걱정할 필요없이 웹 브라우저 (예 : Android 스마트 워치) 이외의 액세스 권한이없는 원격 클라이언트에게 파일을 전송하는 데 유용하다는 것을 알았습니다.

시도해보고 싶다면 bashttpd라는 파일에 복사하여 붙여 넣은 다음 호스트에서 시작하십시오. $> bashttpd -s

그런 다음 다른 컴퓨터로 이동할 수 있습니다 (방화벽이 포트 8080 (기본 포트)에 대한 인바운드 tcp 연결을 차단하지 않는다고 가정하면 스크립트 맨 위에있는 전역 변수를 사용하여 포트를 원하는대로 변경할 수 있습니다). http://bashttpd_server_ip:8080

#!/usr/bin/env bash

#############################################################################
###########################################################################
###                          bashttpd v 1.12
###
### Original author: Avleen Vig,       2012
### Reworked by:     Josh Cartwright,  2012
### Modified by:     A.M.Danischewski, 2015 
### Issues: If you find any issues leave me a comment at 
### http://scriptsandoneliners.blogspot.com/2015/04/bashttpd-self-contained-bash-webserver.html 
### 
### This is a simple Bash based webserver. By default it will browse files and allows for 
### retrieving binary files. 
### 
### It has been tested successfully to view and stream files including images, mp3s, 
### mp4s and downloading files of any type including binary and compressed files via  
### any web browser. 
### 
### Successfully tested on various browsers on Windows, Linux and Android devices (including the 
### Android Smartwatch ZGPAX S8).  
### 
### It handles favicon requests by hardcoded favicon image -- by default a marathon 
### runner; change it to whatever you want! By base64 encoding your favorit favicon 
### and changing the global variable below this header.  
### 
### Make sure if you have a firewall it allows connections to the port you plan to 
### listen on (8080 by default).  
### 
### By default this program will allow for the browsing of files from the 
### computer where it is run.  
###  
### Make sure you are allowed connections to the port you plan to listen on 
### (8080 by default). Then just drop it on a host machine (that has bash) 
### and start it up like this:
###      
### $192.168.1.101> bashttpd -s
###      
### On the remote machine you should be able to browse and download files from the host 
### server via any web browser by visiting:
###      
### http://192.168.1.101:8080 
###  
#### This program requires (to work to full capacity) by default: 
### socat or netcat (w/ '-e' option - on Ubuntu netcat-traditional)
### tree - useful for pretty directory listings 
### If you are using socat, you can type: bashttpd -s  
### 
### to start listening on the LISTEN_PORT (default is 8080), you can change 
### the port below.  
###  E.g.    nc -lp 8080 -e ./bashttpd ## <-- If your nc has the -e option.   
###  E.g.    nc.traditional -lp 8080 -e ./bashttpd 
###  E.g.    bashttpd -s  -or- socat TCP4-LISTEN:8080,fork EXEC:bashttpd
### 
### Copyright (C) 2012, Avleen Vig <avleen@gmail.com>
### 
### Permission is hereby granted, free of charge, to any person obtaining a copy of
### this software and associated documentation files (the "Software"), to deal in
### the Software without restriction, including without limitation the rights to
### use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
### the Software, and to permit persons to whom the Software is furnished to do so,
### subject to the following conditions:
### 
### The above copyright notice and this permission notice shall be included in all
### copies or substantial portions of the Software.
### 
### THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
### IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
### FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
### COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
### IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
### CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
### 
###########################################################################
#############################################################################

  ### CHANGE THIS TO WHERE YOU WANT THE CONFIGURATION FILE TO RESIDE 
declare -r BASHTTPD_CONF="/tmp/bashttpd.conf"

  ### CHANGE THIS IF YOU WOULD LIKE TO LISTEN ON A DIFFERENT PORT 
declare -i LISTEN_PORT=8080  

 ## If you are on AIX, IRIX, Solaris, or a hardened system redirecting 
 ## to /dev/random will probably break, you can change it to /dev/null.  
declare -a DUMP_DEV="/dev/random" 

 ## Just base64 encode your favorite favicon and change this to whatever you want.    
declare -r FAVICON="AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAADg4+3/srjc/5KV2P+ortn/xMrj/6Ch1P+Vl9f/jIzc/3572f+CgNr/fnzP/3l01f+Ih9r/h4TZ/8fN4//P1Oj/3uPr/7O+1v+xu9X/u8XY/9bi6v+UmdD/XV26/3F1x/+GitT/VVXC/3x/x/+HjNT/lp3Z/6633f/E0eD/2ePr/+bt8v/U4+v/0uLp/9Xj6//Z5e3/oKbX/0pJt/9maML/cHLF/3p8x//T3+n/3Ofu/9vo7//W5Oz/0uHq/9zn7f/j6vD/1OLs/8/f6P/R4Oj/1OPr/7jA4f9KSbf/Skm3/3p/yf/U4ez/1ePq/9rn7//Z5e3/0uHp/87e5//a5Ov/5Ovw/9Hf6v/T4uv/1OLp/9bj6/+kq9r/Skq3/0pJt/+cotb/zdnp/9jl7f/a5u//1+Ts/9Pi6v/O3ub/2uXr/+bt8P/Q3un/0eDq/9bj7P/Z5u7/r7jd/0tKt/9NTLf/S0u2/8zW6v/c5+//2+fv/9bj6//S4un/zt3m/9zm7P/k7PD/1OPr/9Li7P/V5Oz/2OXt/9jl7v+HjM3/lZvT/0tKt/+6w+L/2ebu/9fk7P/V4+v/0uHq/83d5v/a5ev/5ezw/9Pi6v/U4+z/1eXs/9bj6//b5+//vsjj/1hYvP9JSLb/horM/9nk7P/X5e3/1eTs/9Pi6v/P3uf/2eXr/+Tr7//O3+n/0uLr/9Xk7P/Y5e3/w8/k/7XA3/9JR7f/SEe3/2lrw//G0OX/1uLr/9Xi7P/T4ev/0N/o/9zn7f/k7PD/zN3p/8rd5v/T4ur/1ePt/5We0/+0w9//SEe3/0pKt/9OTrf/p7HZ/7fD3//T4uv/0N/o/9Hg6f/d5+3/5ezw/9Li6//T4uv/2ubu/8PQ5f9+hsr/ucff/4eOzv+Ei8z/rLja/8zc6P/I1+b/0OLq/8/f6P/Q4Oj/3eft/+bs8f/R4On/0+Lq/9Tj6v/T4Ov/wM7h/9Df6f/M2uf/z97q/9Dg6f/Q4On/1OPr/9Tj6//S4ur/0ODp/93o7f/n7vH/0N/o/8/f5//P3+b/2OXt/9zo8P/c6fH/zdjn/7fB3/+3weD/1eLs/9nn7//V5Oz/0+Lr/9Pi6//e6O7/5u3x/9Pi6v/S4en/0uLp/9Tj6//W4+v/3Ojw/9rm7v9vccT/wcvm/9rn7//X5Oz/0uHq/9Hg6f/S4er/3uju/+bt8f/R4On/0uHp/9Xk6//Y5u7/1OTs/9bk7P/W5Ov/XFy9/2lrwf/a5+//1uPr/9Pi6v/U4er/0eHq/93o7v/v8vT/5ezw/+bt8f/o7vL/6e/z/+jv8v/p7/L/6e/y/9XZ6//IzOX/6e7y/+nv8v/o7vL/5+7x/+ft8f/r8PP/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" 

declare -i DEBUG=1 
declare -i VERBOSE=0
declare -a REQUEST_HEADERS
declare    REQUEST_URI="" 
declare -a HTTP_RESPONSE=(
   [200]="OK"
   [400]="Bad Request"
   [403]="Forbidden"
   [404]="Not Found"
   [405]="Method Not Allowed"
   [500]="Internal Server Error")
declare DATE=$(date +"%a, %d %b %Y %H:%M:%S %Z")
declare -a RESPONSE_HEADERS=(
      "Date: $DATE"
   "Expires: $DATE"
    "Server: Slash Bin Slash Bash"
)

function warn() { ((${VERBOSE})) && echo "WARNING: $@" >&2; }

function chk_conf_file() { 
[ -r "${BASHTTPD_CONF}" ] || {
   cat >"${BASHTTPD_CONF}" <<'EOF'
#
# bashttpd.conf - configuration for bashttpd
#
# The behavior of bashttpd is dictated by the evaluation
# of rules specified in this configuration file.  Each rule
# is evaluated until one is matched.  If no rule is matched,
# bashttpd will serve a 500 Internal Server Error.
#
# The format of the rules are:
#    on_uri_match REGEX command [args]
#    unconditionally command [args]
#
# on_uri_match:
#   On an incoming request, the URI is checked against the specified
#   (bash-supported extended) regular expression, and if encounters a match the
#   specified command is executed with the specified arguments.
#
#   For additional flexibility, on_uri_match will also pass the results of the
#   regular expression match, ${BASH_REMATCH[@]} as additional arguments to the
#   command.
#
# unconditionally:
#   Always serve via the specified command.  Useful for catchall rules.
#
# The following commands are available for use:
#
#   serve_file FILE
#     Statically serves a single file.
#
#   serve_dir_with_tree DIRECTORY
#     Statically serves the specified directory using 'tree'.  It must be
#     installed and in the PATH.
#
#   serve_dir_with_ls DIRECTORY
#     Statically serves the specified directory using 'ls -al'.
#
#   serve_dir  DIRECTORY
#     Statically serves a single directory listing.  Will use 'tree' if it is
#     installed and in the PATH, otherwise, 'ls -al'
#
#   serve_dir_or_file_from DIRECTORY
#     Serves either a directory listing (using serve_dir) or a file (using
#     serve_file).  Constructs local path by appending the specified root
#     directory, and the URI portion of the client request.
#
#   serve_static_string STRING
#     Serves the specified static string with Content-Type text/plain.
#
# Examples of rules:
#
# on_uri_match '^/issue$' serve_file "/etc/issue"
#
#   When a client's requested URI matches the string '/issue', serve them the
#   contents of /etc/issue
#
# on_uri_match 'root' serve_dir /
#
#   When a client's requested URI has the word 'root' in it, serve up
#   a directory listing of /
#
# DOCROOT=/var/www/html
# on_uri_match '/(.*)' serve_dir_or_file_from "$DOCROOT"
#   When any URI request is made, attempt to serve a directory listing
#   or file content based on the request URI, by mapping URI's to local
#   paths relative to the specified "$DOCROOT"
#
#unconditionally serve_static_string 'Hello, world!  You can configure bashttpd by modifying bashttpd.conf.'
DOCROOT=/
on_uri_match '/(.*)' serve_dir_or_file_from 
# More about commands:
#
# It is possible to somewhat easily write your own commands.  An example
# may help.  The following example will serve "Hello, $x!" whenever
# a client sends a request with the URI /say_hello_to/$x:
#
# serve_hello() {
#    add_response_header "Content-Type" "text/plain"
#    send_response_ok_exit <<< "Hello, $2!"
# }
# on_uri_match '^/say_hello_to/(.*)$' serve_hello
#
# Like mentioned before, the contents of ${BASH_REMATCH[@]} are passed
# to your command, so its possible to use regular expression groups
# to pull out info.
#
# With this example, when the requested URI is /say_hello_to/Josh, serve_hello
# is invoked with the arguments '/say_hello_to/Josh' 'Josh',
# (${BASH_REMATCH[0]} is always the full match)
EOF
   warn "Created bashttpd.conf using defaults.  Please review and configure bashttpd.conf before running bashttpd again."
#  exit 1
} 
}

function recv() { ((${VERBOSE})) && echo "< $@" >&2; }

function send() { ((${VERBOSE})) && echo "> $@" >&2; echo "$*"; }

function add_response_header() { RESPONSE_HEADERS+=("$1: $2"); }

function send_response_binary() {
  local code="$1"
  local file="${2}" 
  local transfer_stats="" 
  local tmp_stat_file="/tmp/_send_response_$$_"
  send "HTTP/1.0 $1 ${HTTP_RESPONSE[$1]}"
  for i in "${RESPONSE_HEADERS[@]}"; do
     send "$i"
  done
  send
 if ((${VERBOSE})); then 
   ## Use dd since it handles null bytes
  dd 2>"${tmp_stat_file}" < "${file}" 
  transfer_stats=$(<"${tmp_stat_file}") 
  echo -en ">> Transferred: ${file}\n>> $(awk '/copied/{print}' <<< "${transfer_stats}")\n" >&2  
  rm "${tmp_stat_file}"
 else 
   ## Use dd since it handles null bytes
  dd 2>"${DUMP_DEV}" < "${file}"   
 fi 
}   

function send_response() {
  local code="$1"
  send "HTTP/1.0 $1 ${HTTP_RESPONSE[$1]}"
  for i in "${RESPONSE_HEADERS[@]}"; do
     send "$i"
  done
  send
  while IFS= read -r line; do
     send "${line}"
  done
}

function send_response_ok_exit() { send_response 200; exit 0; }

function send_response_ok_exit_binary() { send_response_binary 200  "${1}"; exit 0; }

function fail_with() { send_response "$1" <<< "$1 ${HTTP_RESPONSE[$1]}"; exit 1; }

function serve_file() {
  local file="$1"
  local CONTENT_TYPE=""
  case "${file}" in
    *\.css)
      CONTENT_TYPE="text/css"
      ;;
    *\.js)
      CONTENT_TYPE="text/javascript"
      ;;
    *)
      CONTENT_TYPE=$(file -b --mime-type "${file}")
      ;;
  esac
  add_response_header "Content-Type"  "${CONTENT_TYPE}"
  CONTENT_LENGTH=$(stat -c'%s' "${file}") 
  add_response_header "Content-Length" "${CONTENT_LENGTH}"
    ## Use binary safe transfer method since text doesn't break. 
  send_response_ok_exit_binary "${file}"
}

function serve_dir_with_tree() {
  local dir="$1" tree_vers tree_opts basehref x
    ## HTML 5 compatible way to avoid tree html from generating favicon
    ## requests in certain browsers, such as browsers in android smartwatches. =) 
  local no_favicon=" <link href=\"data:image/x-icon;base64,${FAVICON}\" rel=\"icon\" type=\"image/x-icon\" />"  
  local tree_page="" 
  local base_server_path="/${2%/}"
  [ "$base_server_path" = "/" ] && base_server_path=".." 
  local tree_opts="--du -h -a --dirsfirst" 
  add_response_header "Content-Type" "text/html"
   # The --du option was added in 1.6.0.   "/${2%/*}"
  read _ tree_vers x < <(tree --version)
  tree_page=$(tree -H "$base_server_path" -L 1 "${tree_opts}" -D "${dir}")
  tree_page=$(sed "5 i ${no_favicon}" <<< "${tree_page}")  
  [[ "${tree_vers}" == v1.6* ]] 
  send_response_ok_exit <<< "${tree_page}"  
}

function serve_dir_with_ls() {
  local dir="$1"
  add_response_header "Content-Type" "text/plain"
  send_response_ok_exit < \
     <(ls -la "${dir}")
}

function serve_dir() {
  local dir="$1"
   # If `tree` is installed, use that for pretty output.
  which tree &>"${DUMP_DEV}" && \
     serve_dir_with_tree "$@"
  serve_dir_with_ls "$@"
  fail_with 500
}

function urldecode() { [ "${1%/}" = "" ] && echo "/" ||  echo -e "$(sed 's/%\([[:xdigit:]]\{2\}\)/\\\x\1/g' <<< "${1%/}")"; } 

function serve_dir_or_file_from() {
  local URL_PATH="${1}/${3}"
  shift
  URL_PATH=$(urldecode "${URL_PATH}") 
  [[ $URL_PATH == *..* ]] && fail_with 400
   # Serve index file if exists in requested directory
  [[ -d "${URL_PATH}" && -f "${URL_PATH}/index.html" && -r "${URL_PATH}/index.html" ]] && \
     URL_PATH="${URL_PATH}/index.html"
  if [[ -f "${URL_PATH}" ]]; then
     [[ -r "${URL_PATH}" ]] && \
        serve_file "${URL_PATH}" "$@" || fail_with 403
  elif [[ -d "${URL_PATH}" ]]; then
     [[ -x "${URL_PATH}" ]] && \
        serve_dir  "${URL_PATH}" "$@" || fail_with 403
  fi
  fail_with 404
}

function serve_static_string() {
  add_response_header "Content-Type" "text/plain"
  send_response_ok_exit <<< "$1"
}

function on_uri_match() {
  local regex="$1"
  shift
  [[ "${REQUEST_URI}" =~ $regex ]] && \
     "$@" "${BASH_REMATCH[@]}"
}

function unconditionally() { "$@" "$REQUEST_URI"; }

function main() { 
  local recv="" 
  local line="" 
  local REQUEST_METHOD=""
  local REQUEST_HTTP_VERSION="" 
  chk_conf_file
  [[ ${UID} = 0 ]] && warn "It is not recommended to run bashttpd as root."
   # Request-Line HTTP RFC 2616 $5.1
  read -r line || fail_with 400
  line=${line%%$'\r'}
  recv "${line}"
  read -r REQUEST_METHOD REQUEST_URI REQUEST_HTTP_VERSION <<< "${line}"
  [ -n "${REQUEST_METHOD}" ] && [ -n "${REQUEST_URI}" ] && \
   [ -n "${REQUEST_HTTP_VERSION}" ] || fail_with 400
   # Only GET is supported at this time
  [ "${REQUEST_METHOD}" = "GET" ] || fail_with 405
  while IFS= read -r line; do
    line=${line%%$'\r'}
    recv "${line}"
      # If we've reached the end of the headers, break.
    [ -z "${line}" ] && break
    REQUEST_HEADERS+=("${line}")
  done
} 

if [[ ! -z "{$1}" ]] && [ "${1}" = "-s" ]; then 
 socat TCP4-LISTEN:${LISTEN_PORT},fork EXEC:"${0}" 
else 
 main 
 source "${BASHTTPD_CONF}" 
 fail_with 500
fi 

POST와 GET을 수락하도록 어떻게 수정합니까?
Adam Dymitruk

@ 아담 Dymitruk 당신은 POST 요청을 (하지 하드가) 여기에서의 모습 최신의 소스 코드에 대한 링크입니다 처리하는 로직을 추가해야 main그것이 말하는 기능 [ "${REQUEST_METHOD}" = "GET" ] || fail_with 405: github.com/AdamDanischewski/bashttpd/blob/master/bashttpd

4

LOL, 슈퍼 절름발이 해킹이지만 적어도 curl 및 firefox는 허용합니다.

while true ; do (dd if=/dev/zero count=10000;echo -e "HTTP/1.1\n\n $(date)") | nc -l  1500  ; done

곧 적절한 것으로 교체하는 것이 좋습니다!

아, 네, nc당신과 똑같지는 않았고, -p옵션이 마음에 들지 않았습니다 .


1
이 답변은 OS X 10.10.1의 netcat에서 작동합니다. 대단해!
HairOfTheDog

4

Apline Linux를 사용하는 경우 BusyBox netcat이 약간 다릅니다.

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

2

nc -h를 입력하고 -e 옵션을 사용할 수 있는지 확인 합니다. 그렇다면 다음과 같은 스크립트를 생성 할 수 있습니다.

script.sh

echo -e "HTTP/1.1 200 OK\n\n $(date)"

다음과 같이 실행하십시오.

while true ; do nc -l -p 1500 -e script.sh; done

참고 -e 옵션의 요구가 컴파일 활성화 할 사용할 수 있습니다.


1

나열된 모든 솔루션이 작동하지 않는다는 문제는 http 서비스의 본질에 내재적이며 설정된 모든 요청은 다른 클라이언트에 있으며 응답은 다른 컨텍스트에서 처리되어야하며 모든 요청은 새로운 응답 사례 ...

내가 생각하는 현재 솔루션 -enetcat있지만 왜 작동하지 않는지 모르겠습니다 ... nc내가 테스트하는 내 버전 일 수 있습니다 openwrt...

socat.... 작동

나는 이것을 시도한다 https://github.com/avleen/bashttpd

작동하지만이 명령으로 쉘 스크립트를 실행해야합니다.

socat tcp-l:80,reuseaddr,fork EXEC:bashttpd &

github 의 socatnetcat샘플은 나를 위해 작동하지 않지만 socat내가 사용한 것은 작동합니다.


reuseaddr플래그 내 일을했다! 감사합니다
WBAR

1

실제로 연결을 정상적으로 닫는 가장 좋은 방법은 Content-Length다음과 같이 헤더 를 보내는 것입니다. 클라이언트 (예 : curl데이터 수신 후 연결을 닫습니다.

DATA="Date: $(date)"; 
LENGTH=$(echo $DATA | wc -c);
echo -e "HTTP/1.1 200 OK\nContent-Length: ${LENGTH}\n\n${DATA}" | nc -l -p 8000;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.