5.2 Programmer le Raspberry Pi comme serveur HTTP

Le même principe s’applique pour programmer notre Raspberry Pi comme serveur. On pourrait le faire avec des sockets ou on peut utiliser des bibliothèques comme http.server et socketserver.

Schéma indiquant les échanges réciproques entre les requêtes d'un objet connecté et les réponses d'un serveur.

Figure 82 — Requêtes d’une application à un objet connecté


5.2.1 Pour fournir une page Web

On peut activer un serveur Web directement dans le terminal du Raspberry Pi avec la commande python -m SimpleHTTPServer 8000 qui permet de servir des pages Web standards contenues dans un dossier du Raspberry Pi. Par contre, si on veut servir une page HTML dynamique pour présenter les données des capteurs de notre objet connecté, on peut le faire en programmant un serveur Web à l’aide des bibliothèques http.server et socketserver. Voir la Figure 83 qui illustre comment hériter de la classe SimpleHTTPRequestHandler pour redéfinir sa méthode do_GET() et ainsi envoyer du code HTML comme réponse à une requête GET. Noter qu’on peut tester ce serveur en le démarrant avec Python 3 et en accédant à l’adresse IP de notre Raspberry Pi dans un navigateur, sans oublier le port, comme dans l’exemple à la Figure 84.

Figure 83 — Serveur HTML dynamique

Figure 83 — Serveur HTML dynamique

URL non sécurisée utilisant le port 8080 pour tester le serveur HTML.

Figure 84 — Test du serveur HTML

Noter que quand on veut modifier et tester notre serveur à répétition, on peut obtenir l’erreur « Address already in use ». Dans ce cas, il faut forcer l’arrêt du processus de notre serveur. On peut trouver le processus avec la commande lsof -i:port et l’arrêter avec kill -term PID, tel qu’illustré à la Figure 85. D’autres fois, si aucun processus n’est trouvé, il peut s’agir d’une question de temps et attendre une ou deux minutes suffit à résoudre le problème.

Figure 85 — Forcer l’arrêt du serveur

Figure 85 — Forcer l’arrêt du serveur

Vidéo 51 : Programmer le Raspberry Pi comme serveur pour fournir des données HTML


5.2.2 Pour fournir un fichier de données JSON

Pour créer un serveur à l’aide des bibliothèques http.server et socketserver, on peut créer une classe qui hérite de la classe SimpleHTTPRequestHandler ou BaseHTTPRequestHandler dans laquelle on pourra implémenter la méthode do_GET(), ainsi que la méthode do_POST() dans le deuxième cas, pour choisir ce que notre objet fera pour répondre à ces requêtes. Voir la Figure 86 pour un exemple d’un serveur qui fournit des données en format JSON. Dans l’exemple, la donnée est toujours la même, mais on pourrait l’adapter pour fournir des données lues par les capteurs de l’objet connecté.

Figure 86 — Code d’un serveur JSON

Figure 86 — Code d’un serveur JSON

Vidéo 52 : Programmer le Raspberry Pi comme serveur pour fournir des données JSON


5.2.3 Pour réagir à des requêtes POST et contrôler les objets

Si on veut aussi que notre serveur puisse recevoir des données sous forme de requêtes POST, on devra plutôt hériter de la classe BaseHTTPRequestHandler dans laquelle on peut implémenter à la fois les méthodes do_GET et do_POST. Voir la Figure 87 pour un exemple où on affiche une valeur reçue à la console, laquelle pourrait éventuellement être utilisée pour contrôler un actuateur.

Figure 87 — Code serveur pour recevoir une requête POST

Figure 87 — Code serveur pour recevoir une requête POST

On peut tester cet exemple avec une requête CURL (client URL request library) telle que : curl -d « valeur=Mon message » -X POST http://192.168.1.109:8080, avec l’adresse IP et le port de notre serveur.

Vidéo 53 : Programmer le Raspberry Pi comme serveur pour recevoir des commandes sous forme de paires clé-valeur

Dans l’exemple précédent, on reçoit un seul paramètre en format de paire clé-valeur. On pourrait aussi préférer recevoir nos données en format JSON, ce qui faciliterait l’extraction des valeurs, comme l’exemple à la Figure 88.

Figure 88 — Recevoir des données JSON dans une requête POST

Figure 88 — Recevoir des données JSON dans une requête POST

On peut aussi tester cet exemple avec une requête CURL comme celle-ci : curl -d {\ »commande\ »:1} -H « Content-Type: application/json » -X POST http://192.168.1.109:8080 Ici, on portera attention à la clé JSON utilisée qui doit être la même que celle qui est attendue par le serveur.

Vidéo 54 : Programmer le Raspberry Pi comme serveur pour recevoir des commandes JSON


5.2.4 Serveur sécurisé

Jusqu’à présent, les données fournies par nos serveurs n’étaient pas chiffrées. On peut y remédier en utilisant la couche SSL (Secure Sockets Layer). Pour ce faire, on aura besoin d’une clé privée et d’un certificat. Normalement, les certificats doivent être délivrés par des autorités reconnues. Par contre, pour les besoins d’apprentissage, de développement ou de prototypage, on peut en générer un nous-mêmes avec OpenSSL. Sur la Figure 89 — Générer une clé privée et un certificat, on peut voir comment utiliser une requête OpenSSL pour créer une clé privée et un certificat, qui seront enregistrés dans les fichiers cle.pem et certificat.pem respectivement. Cette commande nous demande de choisir un mot de passe (PEM pass phrase), qu’on doit entrer deux fois et dont on aura ensuite besoin pour démarrer notre serveur. Il y a aussi d’autres renseignements à fournir, vous pouvez entrer de points « . » pour laisser certains champs vides.

Figure 89 — Générer une clé privée et un certificat

Figure 89 — Générer une clé privée et un certificat

Une fois la clé privée et le certificat générés, on peut revoir les noms de fichiers avec la commande ls, ou même les ouvrir pour voir les données générées, lesquelles sont évidemment chiffrées. On est maintenant prêts à les utiliser pour faire un serveur sécurisé. La Figure 90 — Serveur SSL illustre comment on peut modifier les exemples précédents pour ajouter la couche SSL à nos serveurs. Le tout se joue dans les dernières lignes. On peut utiliser le port 4443 pour tester le SSL, qui utilise normalement le port 443. Ensuite, on configure le socket de notre serveur en lui indiquant l’emplacement des fichiers contenant la clé privée et le certificat générés à l’étape précédente.

Figure 90 — Serveur SSL

Figure 90 — Serveur SSL

Cette fois-ci, quand on démarre notre serveur à l’aide de Python 3, il faut entrer le mot de passe choisi pour la clé et le certificat. Ensuite, on peut tester notre serveur avec une requête CURL. On obtient un message d’erreur indiquant que le certificat ne peut pas être vérifié puisqu’on l’a généré nous-mêmes. C’est bien le résultat attendu ici.

Figure 91 — Test du serveur SSL avec CURL

Figure 91 — Test du serveur SSL avec CURL

Vidéo 55 : Programmer le Raspberry Pi comme serveur sécurisé avec SSL

Vidéo 56 : Intégration de la programmation d’un objet connecté avec Raspberry Pi


5.2.5 Exercices avec un serveur JSON