HTTP-Anfragen mit 4D Request Handlern meistern

Automatisch übersetzt von Deepl

In der heutigen webgesteuerten Welt verarbeiten die Server eine überwältigende Anzahl von Anfragen. Das effiziente Analysieren, Zählen, Interpretieren und Umleiten dieser Anfragen ist von entscheidender Bedeutung, insbesondere bei der Anwendung von MVC Prinzipien.

Mit der Einführung von HTTP Request Handlern auf dem 4D HTTP Server können Sie spezifische Geschäftslogik basierend auf den empfangenen Anfragen auslösen. Diese leistungsstarke Funktion eröffnet viele Möglichkeiten, die in diesem Blogbeitrag näher erläutert werden.

Mit HTTP Request Handlers können Sie so viele Handler wie nötig definieren, die auf bestimmte URL-Muster und HTTP-Verben zugeschnitten sind. Dieser Ansatz bietet eine weitaus größere Granularität als die traditionellen Datenbankmethoden On Web Authentication und On Web Connection und erspart Ihnen die Implementierung umfangreicher Case of Anweisungen.

HDI_HTTP_RequestHandler

Request-Handler – warum?

Die Handhabung von Request-Handlern führt zu verschiedenen Szenarien wie z.B.:

  • Verwendung einer bestimmten URL als Ressourcenanbieter(z. B. Herunterladen verschiedener Dateien durch Aufruf einer bestimmten URL)
  • Verwendung einer bestimmten URL als Datei-Upload-Box(z. B. Hochladen verschiedener Dateien durch Aufruf einer bestimmten URL)
  • Weiterleitung auf bestimmte Seiten je nach Geschäftskontext(z. B. Benutzer authentifiziert oder nicht, Seite nicht gefunden, Berechtigungen gewährt oder nicht … usw.)
  • Statistiken und Informationen zu einer empfangenen Anfrage aufbewahren
  • eine Authentifizierung über oAuth 2.0 abwickeln

wie man einen HTTP-Request-Handler einrichtet

Die HTTP-Request-Handler müssen in der Datei HTTPHandlers.json im Ordner Project/Sources eingerichtet werden.

Diese Datei enthält eine Sammlung von Objekten im JSON-Format. Jedes Objekt verweist auf einen Request-Handler mit den folgenden Informationen:

  • das zu behandelnde URL-Muster
  • das von der URL verwendete Verb
  • die [Singleton-Klasse + Funktion], in der der Request-Handler-Code implementiert ist

Beispiel

HTTPHandlers.json-Datei:

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

Frage: Was bedeutet das?

Antwort: Das bedeutet, dass bei jeder Anfrage, die mit /start/ beginnt und ein GET- oder POST-Verb enthält, die Funktion gettingStarted des Singletons GeneralHandling ausgeführt wird.

wie man den Request-Handler-Code implementiert

Die oben erwähnte Singleton-Klasse muss gemeinsam genutzt werden.

Input: eine Instanz der neuen Klasse 4D.IncomingMessage

Die Anfrage wird auf dem Server als eine Objektinstanz der neuen Klasse 4D.IncomingMessage empfangen.

Die folgenden Informationen sind verfügbar:

  • die vollständige Url der Anfrage
  • die Teile der Url
  • das Verb der Anfrage
  • die Kopfzeilen der Anfrage
  • die in die URL eingefügten Parameter (falls vorhanden)
  • den Textkörper der Anfrage (falls vorhanden)

Anschließend kann der Request Handler all diese Informationen verwenden, um die entsprechende Geschäftslogik auszulösen.

Ausgabe: eine Instanz der Klasse 4D.OutgoingMessage

Bei Bedarf kann der Request Handler ein Objekt der Klasse 4D.OutgoingMessage-Klasse zurückgeben, d.h. einen vollständigen Web-Inhalt, der von einem Browser verarbeitet werden kann (z.B. den Inhalt einer Datei).

Ein einfaches Beispiel für den Anfang

Mit der gleichen HTTPHandlers.json-Datei wie oben:

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

Die Anfrage http://127.0.0.1/start/example?param=demo&name=4D wird mit einem GET-Verb in einem Browser ausgeführt. Sie wird von der Funktion gettingStarted() der folgenden Singleton-Klasse GeneralHandling bearbeitet:

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

Die Anfrage wird auf dem Server als $request (eine Objektinstanz der neuen Klasse 4D.IncomingMessage ) empfangen.

Dieses $request-Objekt enthält die folgenden Eigenschaften:

  • url (String) – URL der Anfrage
  • urlQuery (Object) – Parameter der Anfrage.
  • verb (String) – Verb
  • urlPath (Sammlung von Strings) – URL-Teile der Anfrage

Hier ist die Antwort:

wie man einen Body in der Anfrage behandelt

Die neue Klasse 4D.IncomingMessage bietet einige Funktionen, um die Kopfzeilen und den Body der Anfrage zu erhalten.

Beispiel

Führen wir ein einfaches Beispiel aus, um eine Datei auf den Server hochzuladen.

Die Datei HTTPHandlers.json:

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

Beachten Sie, dass das URL-Muster als regulärer Ausdruck mit der Eigenschaft regexPattern angegeben wird.

Die Anfrage http://127.0.0.1:8044/putFile?fileName=testFile wird mit einem POST-Verb und einem Dateiinhalt in ihrem Body ausgeführt.

Die Singleton-Klasse 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

Der Dateiname wird als Parameter(fileName) in der URL angegeben. Er wird im urlQuery Objekt in der Anfrage empfangen.

Funktionen zum Abrufen der Kopfzeilen und des Body der Anfrage

Im obigen Beispiel ist die Funktion getHeader() zu beachten, die eine bestimmte Kopfzeile der Anfrage zurückgibt. Die Klasse 4D.IncomingMessage bietet auch eine Eigenschaft headers (Object), die alle Kopfzeilen der Anfrage enthält.

Die Kopfzeile Content-Type gibt das Format des empfangenen Körpers an. In diesem Beispiel werden nur die Formate pdf und jpeg verarbeitet.

Beachten Sie die Funktionen getBlob() und getPicture() für das $request-Objekt. Sie liefern den Body-Inhalt im entsprechenden Format, das dem Content-Type-Header entspricht.

In der Dokumentation finden Sie weitere Einzelheiten zu diesen Funktionen.

Eine getText() Funktion ist ebenfalls verfügbar und liefert den Body der Anfrage als String (wenn er als String gesendet wurde)

Wenn der Body als gültige JSON-Darstellung übergeben wurde, liefert die Funktion getJSON() seine Auflösung mit dem richtigen Typ (z. B. Object, Collection, String, …).

Umleitung behandeln

Der Request-Handler ist auch in der Lage, auf eine bestimmte Seite umzuleiten, indem er eine Instanz der Klasse4D.OutgoingMessage zurückgibt. Der Location-Header muss verwendet werden, um die Seite anzugeben, auf die umgeleitet werden soll.

Der Wert des HTTP-Status 3xx zeigt an, dass der Client weitere Maßnahmen ergreifen muss, um die Anfrage abzuschließen.

Lassen wir dieses Szenario laufen:

– Der Benutzer kann alle HTML-Seiten im Ordner WebFolder/pages anzeigen, sobald er authentifiziert ist. Solange der Benutzer nicht authentifiziert ist, wird er auf eine Authentifizierungsseite umgeleitet.

– Befindet sich die angeforderte Seite nicht in diesem Ordner, wird eine Seite „Nicht gefunden“ angezeigt.

– Wenn der Benutzer nach einer Seite in einem Unterordner des Ordners /pages fragt, wird eine Seite mit der Aufschrift Not authorized angezeigt.

Die Datei HTTPHandlers.json:

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

Die Singleton-Klasse 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

Beachten Sie, dass der Request-Handler Zugriff auf das Objekt Session hat, das eine komplexere Geschäftslogik ermöglicht (Überprüfung des Vorhandenseins bestimmter Berechtigungen, Verwendung des gemeinsamen Objekts Session.storage ).

Laden Sie den HDI herunter, um den Umgang mit HTTP-Anfragen zu üben, und warten Sie nicht länger, um in die Welt des Projektmodus einzutreten, der Klassen und andere leistungsstarke Funktionen vorschlägt.

Avatar
- Product Owner - Marie-Sophie Landrieu-Yvert ist seit 2017 als Product Owner im 4D Produktteam tätig. Als Product Owner ist sie für das Schreiben der User Stories und deren Umsetzung in funktionale Spezifikationen zuständig. Ihre Aufgabe ist es auch, sicherzustellen, dass die Implementierung der Funktionen den Anforderungen des Kunden entspricht. Marie-Sophie ist Absolventin der ESIGELEC Ingenieurschule und begann ihre Karriere als Ingenieurin bei IBM im Jahr 1995. Sie nahm an verschiedenen Projekten teil (Wartungs- oder Build-Projekte) und arbeitete als Cobol-Entwicklerin. Dann arbeitete sie als UML-Designerin und Java-Entwicklerin. In letzter Zeit bestand ihre Hauptaufgabe darin, funktionale Anforderungen zu analysieren und zu schreiben sowie Geschäfts- und Entwicklungsteams zu koordinieren.