Maîtriser les requêtes HTTP avec les gestionnaires de requêtes 4D

Traduit automatiquement de Deepl

Dans le monde actuel axé sur le web, les serveurs traitent un nombre impressionnant de requêtes. Il est essentiel d’analyser, de compter, d’interpréter et de réacheminer efficacement ces demandes, en particulier lorsque l’on applique les principes MVC.

Avec l’introduction des gestionnaires de requêtes HTTP sur le serveur HTTP 4D, vous pouvez déclencher une logique commerciale spécifique basée sur les requêtes reçues. Cette fonctionnalité puissante ouvre de nombreuses possibilités, comme le détaille cet article de blog.

Avec les gestionnaires de requêtes HTTP, vous pouvez définir autant de gestionnaires que nécessaire, adaptés à des modèles d’URL et à des verbes HTTP spécifiques. Cette approche offre une granularité beaucoup plus grande que les méthodes traditionnelles d’authentification et de connexion à la base de données sur le Web, ce qui vous évite d’avoir à mettre en œuvre des déclarations Case of exhaustives.

HDI_HTTP_RequestHandler

Pourquoi des gestionnaires de requêtes ?

La gestion des gestionnaires de requêtes conduit à divers scénarios tels que :

  • utiliser une URL donnée comme fournisseur de ressources(par exemple, télécharger divers fichiers en appelant une URL spécifique)
  • utiliser une URL donnée comme boîte de téléchargement de fichiers(par exemple, télécharger divers fichiers en appelant une URL spécifique)
  • gérer la redirection sur des pages spécifiques en fonction d’un contexte commercial(par exemple, utilisateur authentifié ou non, page introuvable, privilèges accordés ou non … etc.)
  • conserver les statistiques et toute information relative à une requête reçue
  • gérer une authentification via oAuth 2.0

comment configurer un gestionnaire de requêtes HTTP

Les gestionnaires de requêtes HTTP doivent être configurés dans le fichier HTTPHandlers.json du dossier Project/Sources.

Ce fichier contient une collection d’objets au format JSON. Chaque objet fait référence à un gestionnaire de requêtes avec les informations suivantes :

  • le modèle d’URL à traiter
  • le verbe utilisé par l’URL
  • la [classe singleton + fonction] où le code du gestionnaire de requête est implémenté

Exemple de fichier

Fichier HTTPHandlers.json :

[
    {
        "class": "GeneralHandling",
        "method": "gettingStarted",
        "pattern": "start",
        "verbs": "get, post"
    }
]

Question: Qu’est-ce que cela signifie ?

Réponse: Cela signifie que lorsqu’une requête commençant par /start/ avec un verbe GET ou POST est reçue sur le serveur, la fonction gettingStarted du singleton GeneralHandling est exécutée.

Comment implémenter le code du gestionnaire de requêtes ?

La classe singleton mentionnée ci-dessus doit être partagée.

Entrée : une instance de la nouvelle classe 4D.IncomingMessage

La demande est reçue sur le serveur sous la forme d’une instance d’objet de la nouvelle classe 4D.IncomingMessage.

Les informations suivantes sont disponibles

  • l’url complète de la demande
  • les parties de l’url
  • le verbe de la requête
  • les en-têtes de la requête
  • les paramètres mis dans l’URL (s’il y en a)
  • le corps de la demande (le cas échéant)

Ensuite, le gestionnaire de la demande peut utiliser toutes ces informations pour déclencher la logique commerciale appropriée.

Résultat : une instance de la classe 4D.OutgoingMessage

Si nécessaire, le gestionnaire de la demande peut renvoyer un objet de la classe 4D.OutgoingMessage, c’est-à-dire un contenu web complet prêt à être traité par un navigateur (par exemple, le contenu d’un fichier).

un exemple simple pour commencer

Avec le même fichier HTTPHandlers.json que ci-dessus :

[
    {
        "class": "GeneralHandling",
        "method": "gettingStarted",
        "pattern": "start",
        "verbs": "get, post"
    }
]

La requête http://127.0.0.1/start/example?param=demo&name=4D est exécutée avec un verbe GET dans un navigateur. Elle est traitée par la fonction gettingStarted() de la classe singleton GeneralHandling ci-dessous :

return $resultshared singleton Class constructor()


Function gettingStarted($request : 4D.IncomingMessage) : 4D.OutgoingMessage

var $result:=4D.OutgoingMessage.new()
var $body : Text

$body:="Called URL: "+$request.url+"\n"

$body+="The parameters are received as an object:"+"\n"+JSON Stringify($request.urlQuery; *)+"\n"

$body+="The verb is: "+$request.verb+"\n"

$body+="There are "+String($request.urlPath.length)+" url parts - Url parts are: "+$request.urlPath.join(" - ")+"\n"+"\n"

$result.setBody($body)
$result.setHeader("Content-Type"; "text/plain")

return $result

La requête est reçue sur le serveur sous la forme de $request (une instance d’objet de la nouvelle classe 4D.IncomingMessage ).

Cet objet $request contient les propriétés suivantes

  • url (String) – URL de la demande
  • urlQuery (Objet) – Paramètres de la demande.
  • verb (Chaîne) – Verbe
  • urlPath (collection de chaînes) – Parties de l’URL de la demande

Voici la réponse :

comment gérer un corps dans la demande

La nouvelle classe 4D.IncomingMessage fournit des fonctions permettant d’obtenir les en-têtes et le corps de la requête.

exemple

Exécutons un exemple simple pour télécharger un fichier sur le serveur.

Le fichier HTTPHandlers.json :

[
    {
        "class": "UploadFile",
        "method": "uploadFile",
        "regexPattern": "/putFile",
        "verbs": "POST"
    }
]

Notez que le modèle d’URL est donné sous forme d’expression régulière avec la propriété regexPattern.

La requête http://127.0.0.1:8044/putFile?fileName=testFile est exécutée avec un verbe POST et un contenu de fichier dans son corps.

La classe singleton UploadFile:

Function uploadFile($request : 4D.IncomingMessage) : 4D.OutgoingMessage
	
var $response:=4D.OutgoingMessage.new()
var $body:="Not supported file"
var $fileName; $fileType : Text
var $file : 4D.File
var $picture : Picture
var $created : Boolean
	
//The file name is given as parameter in the URL
$fileName:=$request.urlQuery.fileName
	
// The header "Content-Type" provides the format of the body
$fileType:=$request.getHeader("Content-Type")
	
Case of 
	// The body contains a pdf file
	: ($fileType="application/pdf")
		$file:=File("/PACKAGE/Files/"+$fileName+".pdf")
		$created:=$file.create()
		// The getBlob() function returns the body of the request as a Blob
		$file.setContent($request.getBlob())
		$body:="Upload OK - File size: "+String($file.size)
			
	// The body contains a jpg image
	: ($fileType="image/jpeg")
		$file:=File("/PACKAGE/Files/"+$fileName+".jpg")
		// The getPicture() function returns the body of the request as a Picture
		$picture:=$request.getPicture()
		WRITE PICTURE FILE($file.platformPath; $picture)
		$body:="Upload OK - Image size: "+String($file.size)
End case 

$response.setBody($body)
$response.setHeader("Content-Type"; "TEXT/plain")
	
return $response

Le nom du fichier est donné en tant que paramètre(fileName) dans l’URL. Il est reçu dans l’objet urlQuery de la requête.

Fonctions permettant d’obtenir les en-têtes et le corps de la requête

Dans l’exemple ci-dessus, notez la fonction getHeader() qui renvoie un en-tête donné de la requête. La classe 4D.IncomingMessage offre également une propriété headers (Object) contenant tous les en-têtes de la requête.

L’en-tête Content-Type fournit le format du corps reçu. Dans cet exemple, seuls les formats pdf et jpeg sont traités.

Notez les fonctions getBlob() et getPicture() sur l’objet $request. Elles fournissent le contenu du corps dans le format approprié qui correspond à l’en-tête Content-Type.

Voir la documentation pour plus de détails sur ces fonctions.

Une fonction getText() est également disponible et fournit le corps de la requête sous forme de chaîne (si elle a été envoyée sous forme de chaîne)

Si le corps de la requête a été envoyé sous la forme d’une représentation JSON valide, la fonction getJSON() fournit sa résolution avec le type correct (par exemple, Object, Collection, String, …).

gérer la redirection

Le gestionnaire de requêtes est également capable de rediriger vers une page spécifique en renvoyant une instance de la classe4D.OutgoingMessage . L’en-tête Location doit être utilisé pour indiquer la page à rediriger.

Le statut HTTP 3xx indique que le client doit prendre des mesures supplémentaires pour compléter la demande.

Exécutons ce scénario :

– L’utilisateur peut visualiser toutes les pages html du dossier WebFolder/pages une fois qu’il est authentifié. Tant que l’utilisateur n’est pas authentifié, il est redirigé vers une page d’authentification.

– Si la page demandée ne se trouve pas dans ce dossier, une page  » Non trouvé » est affichée.

– Si l’utilisateur demande une page dans un sous-dossier du dossier /pages, une page Non autorisée est servie.

Le fichier HTTPHandlers.json :

[
    {
        "class": "PagesHandling",
        "method": "handle",
        "regexPattern": "/pages/"
    }
]

La classe singleton PagesHandling:

shared singleton Class constructor()
	
Function handle($request : 4D.IncomingMessage) : 4D.OutgoingMessage
	
var $result:=4D.OutgoingMessage.new()
var $file : 4D.File
	
//The user is not authenticated
If (Session.isGuest())
	$result.setHeader("Location"; "/authentication/Authentication.html")
	$result.setStatus(307)
Else 
		
	//The URL is an html page in the /pages folder
	If (($request.urlPath.length=2) && (Position(".html"; $request.url)#0))
			
		$file:=File("/PACKAGE/WebFolder"+$request.url)
			
		//The pages exists
		If ($file.exists)
			$result.setBody($file.getContent())
			$result.setHeader("Content-Type"; "text/html")
			$result.setStatus(200)
				
		//The pages does not exist
		Else 
			$result.setHeader("Location"; "/error/NotFound.html")
			$result.setStatus(307)
		End if 
			
	//The URL is NOT a an html page in the /pages folder
	Else 
		$result.setHeader("Location"; "/error/NotAuthorized.html")
		$result.setStatus(307)
	End if 
End if 
	
return $result

Notez que le gestionnaire de requêtes a accès à l’objet Session qui permet une logique d’entreprise plus complexe (vérification de la présence de certains privilèges, utilisation de l’objet partagé Session.storage ).

Téléchargez l’IDH pour vous entraîner à traiter les requêtes HTTP et n’attendez plus pour entrer dans le monde en mode projet proposant des classes et d’autres fonctionnalités puissantes.

Avatar
- Product Owner - Marie-Sophie Landrieu-Yvert a rejoint l'équipe de 4D Product en tant que Product Owner en 2017. En tant que Product Owner, elle est en charge de rédiger les user stories puis de les traduire en spécifications fonctionnelles. Son rôle est également de s'assurer que l'implémentation de la fonctionnalité livrée répond au besoin du client.Marie-Sophie est diplômée de l'école d'ingénieur ESIGELEC et a commencé sa carrière en tant qu'ingénieur chez IBM en 1995. Elle a participé à divers projets (projets de maintenance ou de construction) et a travaillé en tant que développeur Cobol. Elle a ensuite travaillé en tant que concepteur UML et développeur Java. Dernièrement, ses principaux rôles étaient d'analyser et de rédiger des exigences fonctionnelles, de coordonner les équipes commerciales et de développement.