Pregunta Servidor web mínimo usando netcat


Estoy tratando de configurar un servidor web mínimo usando netcat (nc). Cuando el navegador llama localhost: 1500, por ejemplo, debe mostrar el resultado de una función (fecha en el siguiente ejemplo, pero eventualmente será un programa python o c que arroje algunos datos). Mi pequeño servidor web netcat necesita ser un verdadero bucle en bash, posiblemente tan simple como esto:

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

Cuando intento esto, el navegador muestra los datos actualmente disponibles durante el momento en que se inicia nc. Sin embargo, quiero que el navegador muestre los datos durante el momento en que el navegador lo solicite. ¿Cómo puedo conseguir esto?


74
2018-05-19 22:17


origen


Respuestas:


Prueba esto:

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

los -chace que netcat ejecute el comando dado en un shell, para que pueda usar echo. Si no necesita eco, use -e. Para más información sobre esto, intente man nc. Tenga en cuenta que cuando se usa echo no hay forma de que su programa (el date-replacement) para obtener la solicitud del navegador. Entonces, probablemente, finalmente quieras hacer algo como esto:

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

Dónde yourprogram debe hacer el protocolo, como manejar GET, enviar HTTP 200, etc.


30
2017-10-02 14:17



No sé cómo ni por qué, pero logro encontrar esto y me funciona, tuve el problema que quería devolver el resultado de ejecutar un golpe

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

NOTA: Este comando fue tomado de: http://www.razvantudorica.com/08/web-server-in-one-line-of-bash

esto ejecuta la prueba del script bash y devuelve el resultado a un cliente del navegador que se conecta al servidor que ejecuta este comando en el puerto 8080

Mi script hace este cajero automático

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

y mi navegador web está mostrando

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

¡simplemente asombroso!


23
2018-01-18 12:30



El problema al que se enfrenta es que nc no sabe cuando el cliente web finaliza su solicitud para que pueda responder a la solicitud.
Una sesión web debería ser algo como esto.

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.

Las líneas que comienzan con "\ n" son simplemente líneas vacías sin espacio ni contienen nada más que un nuevo carácter de línea.

Tengo mi bash httpd lanzado por xinetd, xinetd tutorial. También registra la fecha, hora, dirección IP del navegador y toda la solicitud del navegador en un archivo de registro, y calcula la longitud del contenido para la respuesta del encabezado del servidor.

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"

Para agregar más funcionalidad, podrías incorporar.

            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

¡Maldición feliz!


17
2017-08-06 17:12



Añadir -q 1 al netcat línea de comando:

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

14
2018-05-19 22:40



Tenía la misma necesidad / problema, pero aquí no funcionó nada (o no entendí todo), así que esta es mi solución.

Publiqué mi minimal_http_server.sh (trabajando con mi / bin / bash (4.3.11) pero no / bin / sh debido a la redirección):

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

Y mi a_script.sh (con su necesidad):

#!/bin/bash

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

date

10
2018-06-21 13:33



Otra forma de hacer esto

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

Probémoslo con 2 solicitudes HTTP usando curl

En este ejemplo, 172.16.2.6 es la dirección IP del servidor.

Lado del servidor

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

Lado del cliente

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

Si desea ejecutar otro comando, puede reemplazar $ (fecha).


6
2018-06-13 10:08



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

4
2017-08-18 06:35