Server web minimal menggunakan netcat


129

Saya mencoba menyiapkan server web minimal menggunakan netcat (nc). Ketika browser memanggil localhost: 1500, misalnya, itu harus menunjukkan hasil dari suatu fungsi ( tanggal dalam contoh di bawah, tetapi pada akhirnya itu akan menjadi program python atau c yang menghasilkan beberapa data). Server web netcat kecil saya perlu menjadi loop yang sebenarnya dalam bash, mungkin sesederhana ini:

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

Ketika saya mencoba ini, browser menunjukkan data yang tersedia saat ini pada saat nc mulai. Saya ingin browser menampilkan data pada saat browser memintanya. Bagaimana saya bisa mencapai ini?


Terima kasih semuanya atas saran yang membawa saya untuk googling lagi. Kebetulan saya menemukan solusi yang sama sekali berbeda di tautan . Saya tidak dapat menggunakan python atau C, tetapi saya sudah mengujinya di semua platform target saya. Masalah dengan netcat adalah ada begitu banyak versi berbeda. Beberapa dari mereka tidak mengizinkan opsi -e, -c atau -q.
andwagon

Jawaban:


52

Coba ini:

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

The -cmerek netcat mengeksekusi perintah yang diberikan di shell, sehingga Anda dapat menggunakan echo. Jika Anda tidak membutuhkan gema, gunakan -e. Untuk informasi lebih lanjut tentang ini, coba man nc. Perhatikan, bahwa saat menggunakan echotidak ada cara untuk program Anda ( date-replacement) untuk mendapatkan permintaan browser. Jadi Anda mungkin akhirnya ingin melakukan sesuatu seperti ini:

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

Di mana yourprogramharus melakukan hal-hal protokol seperti menangani GET, mengirim HTTP 200 dll.


33
OpenBSD netcat bekerja berbeda, Anda dapat melakukan sesuatu sepertiwhile true; do echo -e "HTTP/1.1 200 OK\n\n $(date)" | nc -l localhost 1500; done
matlehmann

2
Dari man untuk nc , -p deskripsi:It is an error to use this option in conjunction with the -l option
sbeliakov

1
Kombinasi -l -p berasal dari pertanyaan dan tampaknya berfungsi untuk penulis pertanyaan. Jadi saya tidak mempertanyakannya, tetapi menggunakannya.
Constantin Berhard

2
Meskipun halaman manual nc yang saya lihat juga mengatakan menggunakan -popsi bersama dengan yang -lada adalah kesalahan, situs web resmi netcat menggunakan kedua opsi dalam contohnya. Lihat: nc110.sourceforge.net
LS

2
Setidaknya ada 3 “rasa” utama nc: Hobbit (asli), BSD / Mac OS X , dan GNU (yang tertua dari kelompok itu, dan tidak lagi dipertahankan). Ada juga Ncat Nmap . Saya mengemukakan ini karena saya pikir perlu dicatat bahwa -ldan -pbersama-sama hanya dianggap sebagai kesalahan dalam rasa BSD nc, maka sintaks alternatif diberikan oleh @matlehmann
Mark G.

39

Tidak tahu bagaimana atau mengapa tetapi saya berhasil menemukan ini di sekitar dan itu berhasil untuk saya, saya punya masalah saya ingin mengembalikan hasil mengeksekusi bash

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

CATATAN: Perintah ini diambil dari: http://www.razvantudorica.com/08/web-server-in-one-line-of-bash

ini menjalankan tes skrip bash dan mengembalikan hasilnya ke klien browser yang terhubung ke server yang menjalankan perintah ini pada port 8080

Skrip saya melakukan ATM ini

$ 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)"

dan browser web saya ditampilkan

************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   |
+----------+------+------+--------+------+-------+

sungguh menakjubkan!


2
lebih baik lakukan http 1.0 karena http 1.1 hanya menambahkan koneksi: keep-hidup yang buruk dalam kasus ini.
Shimon Doodkin

3
@ShimonDoodkin Itu tidak ada gunanya, karena netcat tidak memahami HTTP. Anda mengaktifkan keep-hidup di netcat dengan meneruskan -kbendera, bukan dengan menambahkan Connection: keep-aliveke header permintaan.
Braden Best

1
Bekerja pada versi nc aneh di Mac juga :)
judepereira

28

Tambahkan -q 1ke netcatbaris perintah:

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

3
-q1 tidak bekerja di CentOS6.x apa yang harus digunakan untuk CentOS6.x mana mengatakan: nc: invalid option -- 'q'. while true; do tail -f /usr/local/freeswitch/log/freeswitch.log | nc -l 9999; done &

@YumYumYum Saya menggunakan OS X dan tidak memiliki freeswitch. Apa isi /usr/local/freeswitch/log/freeswitch.log?
HairOfTheDog

3
Menambahkan -q 1berfungsi untuk saya di Ubuntu 18.04. Semoga membantu.
EmpathicSage

20

Masalah yang Anda hadapi adalah bahwa nc tidak tahu kapan klien web selesai dengan permintaannya sehingga dapat menanggapi permintaan tersebut.
Sesi web seharusnya berjalan seperti ini.

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.

Baris yang dimulai dengan "\ n" hanyalah baris kosong bahkan tanpa spasi dan tidak lebih dari karakter baris baru.

Saya memiliki httpd bash saya diluncurkan oleh xinetd, tutorial xinetd . Ini juga mencatat tanggal, waktu, alamat IP browser, dan seluruh permintaan browser ke file log, dan menghitung Panjang Konten untuk respons header Server.

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"

Untuk menambahkan lebih banyak fungsionalitas, Anda dapat menggabungkan.

            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

Selamat menampar!


11

Saya memiliki kebutuhan / masalah yang sama tetapi tidak ada yang berhasil untuk saya (atau saya tidak memahami semuanya), jadi inilah solusi saya.

Saya memposting minimal_http_server.sh saya (bekerja dengan / bin / bash saya (4.3.11) tetapi tidak / bin / sh karena pengalihan):

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

Dan a_script.sh saya (dengan kebutuhan Anda):

#!/bin/bash

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

date

Setelah menjalankan minimal_http_server.sh ketika kita melakukan query url beberapa kali dalam 1 detik itu akan menampilkan halaman tidak ditemukan. Tetapi ketika kami memberikan interval 1 detik untuk setiap permintaan, itu berfungsi dengan baik. Juga perhatikan bahwa ketika kami membiarkan layanan ini berjalan dan memiliki permintaan curl dari skrip shell lain, layanan akan mati atau lumpuh. Tahu apa yang mungkin salah
satish john

@ satishjohn Dari keterampilan saya saat ini (lebih baik daripada saat itu), saya baru saja memperbaiki dua cacat utama ( readdan tr) dan minor ( [mengikuti elif). Saya tidak mereproduksi masalah Anda. Saya tidak mengerti mengapa minimal_http_server.sh akan menyebabkan interval 1 detik ini. Anda dapat menentukan apakah minimal_http_server.sh atau "a_script.sh" Anda yang salah dengan menjalankan beberapa kali (dengan kecepatan yang sama seperti permintaan curl Anda) ./a_script.sh setelah menyetel variabel lingkungan REQUEST.
syme

11

Cara lain untuk melakukan ini

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

Mari kita uji dengan 2 permintaan HTTP menggunakan curl

Dalam contoh ini, 172.16.2.6 adalah Alamat IP server.

Sisi server

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:
*/*

Sisi klien

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:~$

Jika Anda ingin menjalankan perintah lain, silakan ganti $ (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

bagaimana cara kerjanya? read line<pipeakan menunggu sampai ncmenulis pipe? Tetapi pada titik ini, menurut saya permintaan tersebut dilakukan sebelum tanggapan ditulis ..?
fentas

mkfifo membuat pipa pemblokiran, yang berarti perintah echo tidak akan dijalankan sampai nc membaca permintaan.
InvisibleWolf

5

Ini adalah keindahan dari webserver kecil , saya menemukannya online dan membuat salinan dan merapikannya sedikit - itu menggunakan socatatau netcatsaya telah mengujinya socat- itu berdiri sendiri dalam satu skrip dan menghasilkan file konfigurasinya sendiri dan favicon.

Secara default, ini akan dimulai sebagai browser file berkemampuan web namun mudah dikonfigurasi oleh file konfigurasi untuk logika apa pun. Untuk file itu mengalirkan gambar dan musik (mp3), video (mp4, avi, dll) - Saya telah menguji streaming berbagai jenis file ke perangkat Linux, Windows dan Android termasuk jam tangan pintar!

Saya pikir itu streaming lebih baik daripada VLC sebenarnya. Saya merasa ini berguna untuk mentransfer file ke klien jarak jauh yang tidak memiliki akses selain browser web misalnya jam tangan pintar Android tanpa perlu khawatir secara fisik menghubungkan ke port USB.

Jika Anda ingin mencobanya, cukup salin dan tempel ke file bernama bashttpd, lalu mulai di host dengan $> bashttpd -s

Kemudian Anda dapat pergi ke komputer lain (anggap saja firewall tidak memblokir koneksi tcp masuk ke port 8080 - port default, Anda dapat mengubah port ke apa pun yang Anda inginkan menggunakan variabel global di bagian atas skrip). 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 

Bagaimana Anda memodifikasi ini untuk menerima POST dan juga GET?
Adam Dymitruk

@Adam Dymitruk Anda harus menambahkan logika untuk menangani permintaan Post (tidak terlalu sulit), ini adalah tautan ke kode sumber terbaru, lihat di mainfungsi yang bertuliskan [ "${REQUEST_METHOD}" = "GET" ] || fail_with 405: github.com/AdamDanischewski/bashttpd/blob/master/bashttpd

4

LOL, hack super pincang, tapi setidaknya curl dan firefox menerimanya:

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

Lebih baik Anda segera menggantinya dengan sesuatu yang layak!

Ah ya, saya nctidak persis sama dengan milik Anda, tidak suka -ppilihannya.


1
Jawaban ini berfungsi dengan netcat di OS X 10.10.1. Sangat luar biasa!
HairOfTheDog

4

Jika Anda menggunakan Apline Linux, netcat BusyBox sedikit berbeda:

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

2

Ketik nc -h dan lihat apakah Anda memiliki opsi -e . Jika ya, Anda dapat membuat skrip, misalnya:

script.sh

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

dan jalankan seperti ini:

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

Perhatikan bahwa opsi -e harus diaktifkan pada kompilasi agar tersedia.


1

Saya pikir masalah bahwa semua solusi yang tercantum tidak berfungsi, bersifat intrinsik dalam sifat layanan http, setiap permintaan yang dibuat adalah dengan klien yang berbeda dan respons perlu diproses dalam konteks yang berbeda, setiap permintaan harus membuat yang baru contoh respon ...

Solusi saat ini yang menurut saya adalah -edari netcattetapi saya tidak tahu mengapa tidak berhasil ... mungkin ncversi saya yang saya uji openwrt...

dengan socatitu berhasil ....

Saya mencoba https://github.com/avleen/bashttpd ini

dan berhasil, tetapi saya harus menjalankan skrip shell dengan perintah ini.

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

The socatdan netcatsampel pada github tidak bekerja untuk saya, tapi socatyang saya gunakan bekerja.


dengan reuseaddrbendera kamu membuat hariku! TERIMA KASIH
WBAR

1

Sebenarnya, cara terbaik untuk menutup koneksi dengan baik adalah dengan mengirim Content-Lengthheader seperti berikut. Klien (seperti curlakan menutup koneksi setelah menerima data.

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;
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.