LightREST

Composant Serveur REST pour WinDev®
Léger.
Rapide.
Gratuit.
Sans licence Serveur.

La classe lrSession

Par définition un serveur REST est de type “Stateless“, ce qui signifie que l’appelant doit pouvoir appeler une méthode sans aucun contexte préalable (le serveur ne conservant entre deux appels aucune information persistante concernant le client REST).

Nonobstant l’avis des Puristes, un certain pragmatisme peut pousser à transiger avec ce principe de “Stateless” et à stocker sur le serveur des informations contextuelles concernant le client (par exemple l’identité de l’utilisateur, une sélection de dossier en cours, …). Pour éviter de demander à l’appelant de rappeler systématiquement ces informations à chaque appel (ou au code REST d’interroger la base de données pour récupérer à chaque fois les mêmes données), il est pratique de les stocker temporairement sur le serveur et de fournir au client REST un ID de session qu’il pourra rappeler et ainsi permettre au serveur d’accéder aux données de la session.

C’est la raison d’être de la classe lrSession qui va proposer des méthodes pour :

La classe lrSession implémente les Membres, Constantes et Méthodes décrites ci-dessous.

MembreTypeDescription
IDChaineIdentifiant de la session
SessionsDirectoryChaîneRépertoire de stockage des sessions (par défaut sous-répertoire $LR_SESSIONS de l’exécutable)

Code ErreurValeurDésignation
ErrorSessionExpired0x1000Session expirée
ErrorSessionIllegal0x1001Session illégale (ID invalide)
ErrorSessionCannotLoad0x1002Impossible de charger les données de la Session
ErrorSessionCannotSave0x1003Impossible de sauver les données de la Session
ErrorSessionCannotSetValue0x1004Impossible de mémoriser la valeur dans la Session
ErrorSessionCannotDestroy0x1005Impossible de détruire la Session
ErrorSessionCannotDecypher0x1006Impossible de déchiffrer les données de la Session

MéthodeUtilisation
CheckVérifie la signature de l’ID de session et la validité de celle-ci
CreateCréation d’une nouvelle session
DestroyDestruction de la session
GetDataLecture des données de la session
GetErrorMessageRécupération du message d’erreur
RefreshRafraîchissement de la session
SetCypheringKeyDéfinition de la clé de chiffrage
SetDataEcriture des données de la session

Méthode Check() : (booléen, int)

Vérification de la session : Signature valide et session n’ayant pas dépassé le délai maximal d’inactivité (timeout).

Paramètres : Aucun

Retour :

  • booléen : Validité de l’ID de session
  • int : code d’erreur

Exemple :

Procédure REST avec vérification de la validité de la session.
L’identifiant de la session est passé par l’appelant dans un entête SESSION_ID de la requête REST.

PROCEDURE REST_TestSession(pRequest est lrRequest) : lrResponse

oResponse est lrResponse
oSession  est lrSession
bOK       est booleen
eErreur   est entier 

oSession:ID = pRequest::GetHeaderValue("SESSION_ID")

(bOK, eErreur) = oSession:Check()
si bOK alors
  oResponse:Body   = "La session est valide"
  oResponse:Status = lrResponse::StatusOK
sinon
  oResponse:Body   = oSession:GetErrorMessage(eErreur)
  oResponse:Status = lrResponse::StatusUnauthorized  //Statut HTTP 401
fin

oResponse:ContentType = lrResponse::ContentTXT 

RENVOYER oResponse

Méthode Create(Timeout) : booléen

Création d’une nouvelle session, avec expiration automatique lorsque le délai d’inactivité aura dépassé le paramètre Timeout. L’identification de la session comprend une signature qui permet de détecter l’utilisation d’un ID “bricolé” et donc d’identifier une utilisateur suspect (que l’on pourra bloquer avec son adresse IP par exemple).

ParamètreTypeDescription
TimeoutEntierDurée maximale d’inactivité de la session, en Minutes,
Après expiration, celle-ci sera automatiquement détruite

Retour : Booléen. Vrai si session créée, Faux si échec (dans ce cas la fonction ErreurInfo() en donnera la raison).

Exemple :

Création d’une nouvelle session expirant après 600 secondes d’inactivité.
On retourne l’ID de session dans l’entête HTTP de la réponse. L’appelant pourra présenter cet ID dans des appels REST subséquents.

PROCEDURE REST_CreateSession(pRequest est lrRequest) : lrResponse

oSession  est lrSession
oResponse est lrResponse

SI PAS oSession:Create(600) ALORS
  oResponse:Status = lrResponse::StatusInternalServerError //Erreur HTTP 500
  oResponse:Body   = ErreurInfo(errMessage) 
SINON
  oResponse:Status = lrResponse::StatusOK
  oResponse:Body   = "Session "+oSession:ID+" crée"
  oResponse:SetHeaderValue("SESSION_ID", oSession:ID)
FIN

oResponse:ContentType = lrResponse::ContentTXT
RENVOYER oResponse

Méthode Destroy() : (booléen, int)

Détruit la session en cours

Paramètres : Aucun
Retour :

  • booléen : Succès de la destruction
  • int : code d’erreur

Exemple :
Procédure REST de destruction de la session.
L’identifiant de la session est passé par l’appelant dans un entête SESSION_ID de la requête REST.

PROECDURE REST_DestroySession(pRequest est lrRequest) : lrResponse

oSession  est lrSession
oResponse est lrResponse
bOK       est booleen
eErreur   est entier

oSession:ID = pRequest::GetHeaderValue("SESSION_ID")

(bOK, eErreur) = oSession:Destroy()
SI PAS bOK ALORS
  oResponse:Status = lrResponse::StatusUnauthorized  //Statut HTTP 401
  oResponse:Body   = oSession:GetErrorMessage(eErreur)
SINON
  oResponse:Statut = lrResponse::StatusOK
  oResponse:Body   = "Session "+oSession:ID+" détruite"
FIN

oResponse:ContentType = lrResponse::ContentTXT
RENVOYER oResponse

Méthode GetData(Tag) : (Booléen, *)

Lecture de données de session préalablement sauvées.
Le stockage de données multiples étant prévu, chacune est identifiée par une étiquette (ou Tag).

ParamètreTypeDescription
TagChaîneEtiquette de la donnée de session à récupérer

Retour :

  • Booléen : Succès de la lecture
  • * : Donnée telle qu’écrite lors de l’appel à la méthode SetData

Exemple :

Lecture des données de la session en cours

PROCEDURE REST_ReadSession(pRequest est lrRequest) : lrResponse

oSession  est lrSession
oResponse est lrResponse
bOK       est booleen
eErreur   est entier
cData     est chaine

oSession:ID = pRequest:GetHeaderValue("SESSION_ID")

(bOK, cData) = oSession:GetData("AGE_DU_CAPITAINE")
SI PAS bOK ALORS
  oResponse:Status      = lrResponse::StatusInternalServerError //Erreur HTTP 500
  oResponse:Body        = oSession:GetErrorMessage(eErreur)
  oResponse:ContentType = lrResponse::ContentTXT
  RENVOYER oResponse
FIN

oResponse:Body        = "L'âge du capitaine est "+cData
oResponse:ContentType = lrResponse::ContentTXT
RENVOYER oResponse

Méthode GetErrorMessage(Code Erreur) : Chaîne

Récupération du message d’erreur correspondant à un code ErrorSession*, dans la langue courante.

Permet de retourner un message intelligible à l’appelant.

ParamètreTypeDescription
Code ErreurEntierCode de l’erreur dont on souhaite récupérer le message

Retour : Chaîne. Message de l’erreur

Exemple :

Voir l’exemple de la méthode Check() qui fait appel à GetErrorMessage()


Méthode Refresh() : (booleen, entier)

Rafraîchit l’horodateur du dernier accès de la session.
Cette fonction est à appeler lorsque l’utilisateur effectue une action susceptible de réinitialiser le délai d’inactivité de sa session.
NB : Les méthodes GetData() et SetData() effectuent automatiquement un Refresh()

Paramètres : Aucun

Retour :

  • Booléen : Succès ou pas du démarrage
  • Entier : Numéro d’erreur

Exemple :
Traitement effectuant un rafraîchissement de la session

PROCEDURE REST_FaitQuelqueChose(pRequest est lrRequest) : lrResponse

oSession  est lrSession
oResponse est lrResponse
bOK       est booleen 
eErreur   est entier
cData     est chaine

oSession:ID = pRequest::GetHeaderValue("SESSION_ID")

//On rafraîchit la session pour éviter qu'elle expire
(bOK, eErreur) = oSession:Refresh()
SI PAS bOK ALORS
  oResponse:Status      = lrResponse::StatusUnauthorized  //Statut HTTP 401
  oResponse:Body        = oSession:GetErrorMessage(eErreur)
  oResponse:ContentType = lrResponse::ContentTXT
  RENVOYER oResponse
FIN

...
...
traitement
...
...


oResponse:ContentType = lrResponse::ContentTXT
RENVOYER oResponse

Méthode SetCypheringKey(Clé)

Initialise la clé de chiffrement des sessions.
Si aucune clé n’a été initialisée, les données de session seront sauvées en clair au format JSON.

Attention, il ne faut pas changer la clé de chiffrement pendant l’exécution, sinon les données de session déjà sauvegardées deviendront illisibles.

ParamètreTypeDescription
Clé de chiffrementBufferClé de chiffrement des données de session
En l’absence de clé de chiffrement, les données de session seront écrites en clair au format JSON

Retour : Aucun


Méthode SetData(Tag, Data) : (Booléen, Entier)

Ecriture de données de session.
Le stockage de données multiples étant prévu, chacune est identifiée par une étiquette (ou Tag).

ParamètreTypeDescription
TagChaineEtiquette de la donnée de session à sauver
DataTout type de donnée stockable dans un variantDonnée de session à mémoriser

Retour :

  • Booléen : Succès de la lecture
  • Entier : Code d’Erreur

Exemple :

Ecriture des données de la session en cours

PROCEDURE REST_WriteSession(pRequest est lrRequest) : lrResponse

oSession  est lrSession
oResponse est lrResponse
bOK       est booleen
eErreur   est entier
cData     est chaine

oSession:ID = pRequest::GetHeaderValue("SESSION_ID")

cData = hasard(10,100)

(bOK, cData) = oSession:SetData("AGE_DU_CAPITAINE", cData)
SI PAS bOK ALORS
  oResponse:Status      = lrResponse::StatusInternalServerError //Erreur HTTP 500
  oResponse:Body        = oSession:GetErrorMessage(eErreur)
  oResponse:ContentType = lrResponse::ContentTXT
  RENVOYER oResponse
FIN

oResponse:Body        = "On a bien enregistré dans la session l'âge du capitaine : "+cData
oResponse:ContentType = lrResponse::ContentTXT
RENVOYER oResponse