Articles taggés web

mongoose_64x64@2

Serveur web embarqué

0

Déployer une application web, ça n’est pas forcément ouvrir un site qui va accueillir des milliers de personnes et sera disponible sur internet, c’est aussi profiter d’une interface en client léger, et permettre à tous les périphériques du réseau local (ordinateurs, tablettes, téléphones …) d’accéder à votre application.

Cependant, même si de plus en plus de machines permettent de se trimbaler un système d’exploitation, telles que les Raspberry Pi notamment, déployer un serveur Apache et des scripts PHP « classiques » n’est pas toujours une très bonne idée, pour toutes les raisons de performances que l’on peut imaginer.

C’est pour cela qu’il est intéressant de disposer d’un serveur web léger et capable de s’interfacer facilement avec une application bas niveau, par exemple écrite en C++.

C’est en recherchant cela que je suis tombé sur mongoose, un serveur web embarqué qui tient en tout dans un unique fichier C et très léger. Il a d’ailleurs acquis une certaine popularité sur Github. Sur ma machine, il se compile en moins de 2 secondes et ses performances semblent très acceptables. Il supporte également plusieurs features avancés tels que l’upload de fichier ou les websockets.

Seul hic, le développement avec ce mongoose « brut » n’est pas très élégant, car il faut jongler avec des structures de données et une API en C. L’exemple de traitement des requêtes POST donne un peu mal à la tête.

C’est pour cela que j’ai créé un fork de mongoose afin d’y apporter une API C++ permettant d’utiliser beaucoup plus facilement les fonctionnalités du serveur web.

Exemple

Voici un hello world d’exemple, qui répond aux requêtes sur la page /hello?name=Nom en affichant le nom de l’utilisateur echappé:

#include <stdlib.h>
#include <signal.h>
#include <mongoose/Server.h>
#include <mongoose/WebController.h>

using namespace std;
using namespace Mongoose;

class MyController : public WebController
{
    public:
        void hello(Request &request, StreamResponse &response)
        {
            response << "Hello " << htmlEntities(request.get("name", "... what's your name ?")) << endl;
        }

        void setup()
        {
            addRoute("GET", "/hello", MyController, hello);
        }
};

int main()
{
    MyController myController;
    Server server(8080);
    server.registerController(&myController);

    server.start();

    while (1) {
        sleep(10);
    }
}

Dans cet exemple, un serveur web est créé, et sert par défaut les fichiers statiques du dossier www/ à partir du dossier d’exécution du serveur, sur le port 8080.

De plus, grâce à un système de contrôleur enregistré auprès du serveur, il répondra également aux requêtes GET sur l’URL /hello, en appelant la méthode hello du contrôleur.

La réponse hérite en fait ici de ostringstream, ce qui permet de lui ajouter des données simplement avec l’opérateur « << ».

Comme vous le voyez, accéder aux paramètres GET de la requête est aussi très facile à l’aide de request.get().

Comme on peut le voir dans un autre exemple plus complet, mon API permet également de manipuler des variables de sessions, les variables POST, et aussi de changer les en-têtes de la réponse.

Il est également possible de modifier le type de la réponse utilisée par les routes, et de créer ainsi par exemple un serveur web supportant une API JSON.

Application

Ce système peut permettre d’embarquer facilement un serveur web dans n’importe quelle application « lourde » C++. Et ce indépendamment de toute grosse bibliothèque qui pourrait exister (pour ne pas citer Qt ou boost par exemple).

C’est donc en effet approprié pour une utilisation dans l’embarqué comme par exemple une exécution à bord d’un petit ordinateur tel que la Raspberry Pi ou d’un MK802. Il pourrait être utilisé pour piloter un robot ou un appareil (routeur, télévision, serveur divers…).

Conclusions

Comme je risque de m’en servir dans de futurs projets, je compte continuer de maintenir mongoose-cpp et de merger mongoose de temps en temps pour rester à jour. J’aimerais aussi y ajouter une manière simple d’utiliser les websockets, comme cela est permis par mongoose.

Ce qui est assez remarquable, c’est l’intérêt de cette architecture qui utilise un outil très léger entièrement écrit en C pour y ajouter une fine couche d’ingénieurie logiciel, ce qui fait au final un outil à la fois performant et facile à utiliser. Implémenter un serveur web intégralement en C++ avec un génie logiciel au cordeau aurait sans doute donné une application nettement plus longue à compiler et moins performante.

Liens

Guide de conception PHP

2

Comme chacun le sait, il existe plusieurs PHP, du très bon au très mauvais. On trouve aujourd’hui sur internet de très (trop) nombreuses sources pour apprendre le PHP, des cours, leçons et tutoriels.

Je donne moi-même un cours de PHP à des étudiants de licence professionnelle, et aborder cet enseignement s’avère assez compliqué, car les étudiants parviennent en général à réaliser quelque chose de fonctionnel, en laissant malheureusement de nombreuses bonnes pratiques de coté, ou en utilisant des fonctionnalités obsolètes de PHP.

PHP est historiquement un langage très répandu et facile à utiliser, et les cours, tutoriels ou exemple que l’on trouve sur internet sont souvent préférés par les gens pour leur facilité de prise en main que pour leur qualités techniques.

Par exemple, le tutoriel numéro 1 de developpez.com sur le PHP (cf http://php.developpez.com/cours/) date de 2009, nous propose d’utiliser les obselètes fonctions mysql_connect & co, et de construire des requêtes non échappées par concaténation. Les cours du Site du Zéro ont l’air quant à eux de bien meilleure facture.

Suite aux projets de l’année dernière, j’ai pu lister quelques uns des problèmes les plus fréquents, et j’ai produit un guide de conception que l’on peut trouver ici:

http://gregwar.com/php/guide-de-conception.html

Ce guide a pour but d’imposer des règles relativement strictes pour essayer de respecter les concepts modernes du développement en PHP.

Toutes les remarques à ce sujet seront les bienvenues !

Haut de page