Être paranoïaque !

Développer une API REST ne consiste pas seulement à exposer des routes HTTP qui renvoient des données. Dès qu’une API devient accessible sur un réseau — et plus encore sur Internet — elle devient immédiatement une surface d’attaque potentielle, un point d’entrée pour des comportements imprévus, ou un vecteur de surcharge involontaire.

Avec LightREST, il est très simple de créer rapidement un serveur REST performant. Mais cette simplicité ne doit jamais faire oublier que l’on développe un composant serveur concurrent, capable de traiter plusieurs requêtes simultanément, parfois provenant de clients inconnus ou malveillants. Ce qui est valable quelle que soit la technologie ou le protocole de communication utilisés.

Dans ce contexte, la prudence n’est pas une option. Un développeur d’API doit adopter une approche presque paranoïaque : considérer que toute entrée peut être invalide, que toute ressource peut être sollicitée en parallèle, et que tout comportement inattendu finira un jour par se produire en production.

Une API publique doit être conçue pour résister à :

C’est précisément pour cette raison qu’il est essentiel d’appliquer un ensemble de bonnes pratiques lors du développement d’un serveur LightREST. Ces pratiques permettent de construire des API plus robustes, plus sûres et plus maintenables dans le temps.

Les recommandations présentées ci-dessous ne sont pas de simples conseils de style. Elles correspondent aux principes fondamentaux de conception des services REST modernes : gestion correcte de la concurrence, isolation des requêtes, validation systématique des entrées, maîtrise des ressources et respect des conventions d’architecture.

Adopter ces pratiques dès le départ permet d’éviter des problèmes difficiles à diagnostiquer en production et garantit que votre serveur LightREST restera stable, sécurisé et performant, même lorsque la charge ou l’exposition publique augmentera.

LightREST est un serveur REST concurrent. Une même route peut être exécutée simultanément par plusieurs requêtes.

Les principes fondamentaux sont :


Pas de connexion base de données globale

Une connexion base de données unique, partagée entre toutes les routes, est une mauvaise pratique en environnement serveur concurrent.

Cela peut provoquer :

Même si le handler LightREST est exécuté dans un contexte Hyperfile dédie, la bonne pratique consiste à ouvrir la connexion pour chaque requête à a y affecter les tables de l’analyse, généralement via un hook exécuté avant le handler, puis à la fermer dans un hook de fin. Les moteurs de base de données gérant des pools de connexions disponibles, le processus est très rapide.

Exemple :

Copier

PROCÉDURE HookBeforeMethod(pEventInfo est objet lrHook:EventInfo) : lrHook:EventReturn

cnxDB est une Connexion

//définir les paramètres de la connexion......

SI PAS HOuvreConnexion(cnxDB ) ALORS
    pEventInfo:Response:Status = lrResponse::StatusInternalServerError
    pEventInfo:Response:ContentType = lrReponse::ContentTXT
    pEventInfo:Response:Body = Herreuurinfo()
    RENVOYER lrHook:EVE_ABORT
FIN
    
pRequest:DatabaseConnexion["DB"] = cnxDB 
hChangeConnexion("*", cnxDB )

RENVOYER lrHook:EVE_OK

Puis dans le handler :

Copier

PROCÉDURE HookAfterMethod(pEventInfo est objet lrHook:EventInfo) : lrHook:EventReturn

SI pRequest:DatabaseConnexion["DB"]..existe ALORS
    hFermeConnexion(pRequest:DatabaseConnexion["DB"])
FIN
RENVOYER lrHook:EVE_OK

Éviter les variables globales dans les handlers

Dans LightREST, plusieurs requêtes peuvent accéder au même moment au même code et aux mêmes données.

Une variable globale non protégée peut donc devenir une source :

Exemple à éviter :

Copier

gCompteur++

Si un état partagé est réellement nécessaire, il doit être protégé par un mécanisme de synchronisation ou stocké dans une structure adaptée.


Partager proprement des données globales avec LightREST

LightREST fournit les membres CustomData à plusieurs niveaux :

C’est la méthode recommandée pour associer des données de contexte sans multiplier les variables globales dispersées.

Exemple :

Copier

oServer:CustomData["Config"] = maConfiguration

Puis dans le handler :

Copier

cfg est un Config = poRequest:ServerCustomData["Config"]


Cette approche rend le code plus clair, mieux structuré et plus sûr.


Limiter l’utilisation des objets ou ressources partagés entre plusieurs handlers

Le plus sûr est d’éviter ce cas de figure. Si toutefois c’est incontournable, il faut que leur accès soit maîtrisé.

Toute ressource partagée doit être :

Par exemple, si plusieurs handlers modifient un même compteur ou une même structure, il faut sécuriser l’accès par section critique (https://doc.pcsoft.fr/fr-FR/?1000021292), sémaphore (https://doc.pcsoft.fr/fr-FR/?3077013) ou autre mécanisme approprié.

Copier

SectionCritiqueDébut(gsLock)
gCompteur++
SectionCritiqueFin(gsLock)

Ne pas exposer les identifiants techniques dans les routes

Exposer directement un identifiant base de données dans une URL facilite :

Exemple à éviter :

Copier

GET /clients/1287

Il est préférable d’exposer un identifiant chiffré ou obfusqué via les fonctions :

Exemple :

Copier

GET /clients/03980608-5abe9581-7fee65e9-194ae106

Puis dans le handler :

Copier

nID est entier = DecipherID(pRequest:GetUrlValue("id"))

//Ici nID = 1287

Rester stateless

Oui. Une API REST doit rester aussi stateless que possible.

Une requête ne doit pas dépendre d’un état conservé implicitement dans le serveur ou dans un handler précédent.

Il faut éviter par exemple :

Chaque requête doit porter elle-même les informations nécessaires via :


Éviter les variables globales dans les handlers

Un handler REST doit répondre rapidement.

Un traitement long monopolise inutilement les ressources du serveur et dégrade la capacité à traiter d’autres requêtes.
A partir de la version 3.3, LightREST propose un système de Workers qui permettent d’exécution des traitements longs de façon asynchrone et de libérer immédiatement le handler en cours.

Il est préférable de :

Exemple de réponse :

Copier

{
  "status": "accepted",
  "jobId": "12345"
}

Centraliser l’authentification

Centraliser l’authentification avec un Hook EVE_BEFORE_HANDLER évite la duplication de code dans chaque route et réduit le risque d’oublis ou d’incohérences.

La fonction dédiée permet d’appliquer une logique homogène sur l’ensemble du serveur ou sur un groupe de routes.

Copier

SetAuthenticationCheckFunction()

Une authentification centralisée améliore :


Centraliser les logs

Une API en production doit permettre de comprendre ce qu’il se passe en cas d’erreur, de lenteur ou d’usage anormal.

Il faut journaliser au minimum :

Hooks utiles :


Limiter le volume des réponses

Retourner des volumes massifs de données ralentit :

Il est préférable d’utiliser :

Copier

GET /clients?page=1&limit=50

Cette pratique améliore à la fois les performances et l’expérience d’intégration côté client.


Valider systématiquement les entrées

Un bon développeur d’API se doit d’être PARANOÏAQUE ! Une API ne doit jamais faire confiance aux données reçues.

Il faut valider :

Copier

sID = pRequest:GetUrlValue("id")

SI sID = "" ALORS
    oResponse:Status = lrResponse::StatusBadRequest
FIN

Ne jamais exposer le détail des erreurs techniques

C’est très important pour une API publique.

Une API ne doit jamais renvoyer directement des erreurs internes du serveur ou de la base de données, qui peuvent contenir des extraits de code, le contenu de variables, des requêtes SQL ou des données.

Exemples dangereux :

Copier

SQL error near column CLIENT_ID
File not found: /var/data/config.ini
Stack trace...

Ces informations peuvent révéler :

La bonne pratique consiste à renvoyer des messages d’erreur contrôlés.

Exemple :

Copier

{
"error": "internal_error",
"message": "An unexpected error occurred"
}

Les détails techniques doivent être enregistrés uniquement dans les logs serveur.
NB : Le niveau de détail des erreurs gérées automatiquement par LightREST est réglable par la propriété lrServer:WindevErrorDetail.


Ajouter un endpoint de santé (health check)

Très utilisé en production.

Un serveur API devrait exposer une route simple permettant de vérifier son état.

Exemple :

Copier

GET /health

Réponse :

Copier

{
"status": "ok"
}

Ce type de route est utilisé par :


Respecter les conventions REST

ActionRoute
listeGET /clients
détailGET /clients/{id}
créationPOST /clients
modificationPUT /clients/{id}
suppressionDELETE /clients/{id}

Une API cohérente réduit la documentation nécessaire et facilite l’adoption.LightREST V3 marque une évolution majeure : plus ouvertplus flexibleplus sécurisé, et plus robuste en production.
Cette page récapitule les nouveautés principales et surtout ce qu’elles apportent concrètement au quotidien.