Un serveur web en une ligne de python
Je me doute que tout le monde connaît l'astuce mais je me suis dit que le sujet était assez facile pour me remettre le pied à l'étrier de l'écriture.
Parfois, on a juste besoin d'un serveur web basique, sans fioritures. Pas de pages dynamiques, juste servir des fichiers statiques, quelques logs, et éventuellement lister le contenu d'un répertoire s'il n'y a pas de page d'index. Deux exemples typiques de ce cas de figure au moment d'écrire ce texte, ce blog, et la page principale de ce domaine : j'utilise une simple ligne de Python pour avoir un serveur web "de développement" et faire mes essais en local avant publication. Utilisant Fedora Linux sur ma machine personnelle principale, j'ai toujours un interpréteur Python récent sous la main, donc pas besoin d'installer des dépendances supplémentaires (même si j'en ai, pour d'autres raisons).
La commande est donc la suivante :
python3 -m http.server
Oui, j'avoue, ça fait un peu l'effet d'un pétard mouillé, mais nous n'en sommes qu'au début. D'abord, petite description de ce que fait ce petit bout de code : il lance un serveur web, via Python, sur le port 8000 (port par défaut), et surtout cela va écouter sur toutes les adresses disponibles. Mais le bougre ne s'arrête pas là ! Si vous avez fait la manipulation chez vous, vous aurez remarqué que la commande n'a pas rendu la main. En allant sur http://127.0.0.1:8000, vous pourrez voir que les logs d'accès s'affichent tout pendant que vous requêtez le serveur. Pratique, non ? Pour couper tout ça, un bon vieux Ctrl+c
fera l'affaire. À noter que le répertoire servi est le répertoire courant dans lequel se situe le shell lors de l'invocation de la commande. Il vaut mieux donc éviter de faire cela si on est dans /etc/
ou un autre répertoire sensible.
Maintenant, allons plus loin. Comme indiqué plus haut, le serveur écoute sur le port 8000 par défaut, mais moi ça m'ennuie, car pas mal d'outils démarrant un serveur web vont utiliser soit ce port, soit 8080. Et comme il m'arrive d'être étourdi, j'aimerais utiliser un port différent pour avoir potentiellement plusieurs de ces outils en parallèle, par exemple, ce blog mais aussi la page principale. Pour cela rien de plus simple, il suffit de spécifier le numéro du port souhaité en argument après :
python3 -m http.server 8123
Dans cet exemple, le port choisi est donc 8123. Et s'il est occupé ? Un certain nombre d'erreurs s'afficheront, mais la dernière ligne est assez explicite :
OSError: [Errno 98] Address already in use
Mais j'entends encore des voix pour qui ce n'est pas assez. Vous en voulez encore ? Fort bien. Comme l'objectif est d'avoir un serveur de test, pas besoin d'écouter sur toutes les interfaces ni adresses IP de la machine. Limitons notre serveur à l'adresse locale, comme ceci :
python3 -m http.server --bind 127.0.0.1 8123
D'après la documentation officielle, il est possible d'écouter en IPv4 ou en IPv6 (j'ai testé en remplaçant 127.0.0.1 par ::1), et cela fonctionne).
Deux autres options peuvent s'avérer utiles : * --directory
va permettre de spéficier un répertoire précis au lieu du répertoire courant ; * et --protocol
va permettre de changer la version du protocole HTTP utilisée (1.0 par défaut)
Une dernière chose : il est aussi possible d'exécuter ce serveur web en arrière-plan avec un simple &
à la fin de la commande, et même de rediriger les messages de la sortie standard dans un fichier ou dans /dev/null
. Mon petit truc (et c'est le dernier) c'est d'avoir implémenté cela dans un Makefile, justement pour ma page principale. Voici un extrait de celui-ici :
PORT ?= 0
ifneq ($(PORT), 0)
HTTP_PORT += $(PORT)
else
HTTP_PORT += 8001
endif
serve:
cd ${OUTPUTDIR} && python3 -m http.server --protocol HTTP/1.1 --bind 127.0.0.1 ${HTTP_PORT}
bg_serve:
cd ${OUTPUTDIR} && python3 -m http.server --protocol HTTP/1.1 --bind 127.0.0.1 ${HTTP_PORT} &
Je me rappelle avoir vu passer un dépôt ou un gist sur GitHub, proposant d'autres one-liners comme celui-ci mais pour d'autres langages. J'espère remettre la main dessus bientôt pour en essayer d'autres, mais j'avoue que celui-ci me plaît déjà beaucoup.
J'espère que vous avez aimé lire cet article ! N'hésitez pas à le partager sur vos réseaux sociaux :-)
Photo par Rubaitul Azad, disponible sur Unsplash.