171 votes

Serveur web minimal utilisant netcat

J'essaie de mettre en place un serveur web minimal en utilisant netcat (nc). Lorsque le navigateur appelle localhost:1500, par exemple, il doit afficher le résultat d'une fonction ( date dans l'exemple ci-dessous, mais éventuellement ce sera un programme python ou c qui produira des données). Mon petit serveur web netcat doit être une boucle while true en bash, peut-être aussi simple que ceci :

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

Lorsque j'essaie ceci, le navigateur affiche les données actuellement disponibles au moment où nc démarre. Mais je veux que le navigateur affiche les données au moment où le navigateur les demande. Comment puis-je y parvenir ?

82voto

Essayez ça :

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

El -c fait en sorte que netcat exécute la commande donnée dans un shell, afin que vous puissiez utiliser echo. Si vous n'avez pas besoin d'echo, utilisez -e . Pour plus d'informations à ce sujet, essayez man nc . Notez que lorsque vous utilisez echo il n'y a aucun moyen pour votre programme (le date -replacement) pour obtenir la requête du navigateur. Donc vous voulez probablement finalement faire quelque chose comme ceci :

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

Donde yourprogram doit faire les choses du protocole comme gérer GET, envoyer HTTP 200 etc.

47voto

maco1717 Points 545

J'ai eu un problème où je voulais retourner le résultat de l'exécution d'une commande bash :

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

NOTE :
Cette commande a été prise de : http://www.razvantudorica.com/08/web-server-in-one-line-of-bash

Ceci exécute un script bash et renvoie le résultat à un client navigateur se connectant au serveur exécutant cette commande sur le port 8080.

Mon script fait cela :

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

et mon navigateur web affiche

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

41voto

Ansgar Wiechers Points 38466

Ajouter -q 1 au netcat ligne de commande :

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

24voto

Keith Reynolds Points 485

Le problème auquel vous êtes confronté est que nc ne sait pas quand le client web a terminé sa requête afin de pouvoir y répondre.
Une session web devrait se dérouler comme suit.

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.

Les lignes qui commencent par " \n "sont simplement des lignes vides sans même un espace et ne contiennent rien de plus qu'un caractère de nouvelle ligne.

J'ai mon httpd bash lancé par xinetd, Tutoriel xinetd . Il enregistre également la date, l'heure, l'adresse IP du navigateur et l'ensemble de la requête du navigateur dans un fichier journal, et calcule la longueur du contenu de la réponse de l'en-tête du serveur.

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"

Pour ajouter plus de fonctionnalités, vous pourriez incorporer.

            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

Joyeux bashing !

19voto

Charlotte Russell Points 463

Une autre façon de procéder

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

Testons-le avec 2 requêtes HTTP en utilisant curl.

Dans cet exemple, 172.16.2.6 est l'adresse IP du serveur.

Côté serveur

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

Côté client

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 vous voulez exécuter une autre commande, n'hésitez pas à remplacer $(date).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X