Nell’odierno mondo guidato dal web, i server elaborano un numero spropositato di richieste. Analizzare, contare, interpretare e reindirizzare queste richieste in modo efficiente è essenziale, soprattutto quando si applicano i principi MVC.
Con l’introduzione dei gestori di richieste HTTP sul server HTTP 4D, è possibile attivare una logica aziendale specifica in base alle richieste ricevute. Questa potente funzione apre molte possibilità, come illustrato in dettaglio in questo post del blog.
Con i gestori di richieste HTTP, è possibile definire tutti i gestori necessari, adattati a specifici modelli di URL e verbi HTTP. Questo approccio offre una granularità molto maggiore rispetto ai tradizionali metodi di database On Web Authentication e On Web Connection, risparmiandovi l’implementazione di estese dichiarazioni Case of.
perché i gestori di richieste?
La gestione dei gestori di richieste porta a vari scenari, quali:
- utilizzare un determinato URL come fornitore di risorse(ad esempio, scaricare vari file richiamando un URL specifico)
- utilizzare un determinato URL come casella per il caricamento di file(ad esempio, caricare vari file chiamando un URL specifico)
- gestire il reindirizzamento su pagine specifiche in base a un contesto aziendale(ad esempio, utente autenticato o meno, pagina non trovata, privilegi concessi o meno … ecc.)
- persistere le statistiche e tutte le informazioni relative a una richiesta ricevuta
- gestire un’autenticazione tramite oAuth 2.0
come impostare un gestore di richieste HTTP
I gestori di richieste HTTP devono essere impostati nel file HTTPHandlers.json nella cartella Project/Sources.
Questo file contiene una raccolta di oggetti in formato JSON. Ogni oggetto si riferisce a un gestore di richieste con le seguenti informazioni:
- il modello di URL da gestire
- il verbo utilizzato dall’URL
- la [classe singleton + funzione] in cui è implementato il codice del gestore della richiesta
esempio
File HTTPHandlers.json:
[
{
"class": "GeneralHandling",
"method": "gettingStarted",
"pattern": "start",
"verbs": "get, post"
}
]
Domanda: Cosa significa?
Risposta: Significa che quando una qualsiasi richiesta che inizia con /start/ con un verbo GET o POST viene ricevuta sul server, viene eseguita la funzione gettingStarted del singleton GeneralHandling.
come implementare il codice del gestore delle richieste
La classe singleton di cui sopra deve essere condivisa.
Input: un’istanza della nuova classe 4D.IncomingMessage
La richiesta viene ricevuta sul server come istanza di un oggetto della nuova classe 4D.IncomingMessage.
Sono disponibili le seguenti informazioni:
- l’URL completo della richiesta
- le parti dell’url
- il verbo della richiesta
- le intestazioni della richiesta
- i parametri inseriti nell’URL (se presenti)
- il corpo della richiesta (se presente)
Quindi, il gestore della richiesta può utilizzare tutte queste informazioni per attivare la logica aziendale appropriata.
Output: un’istanza della classe 4D.OutgoingMessage
Se necessario, il gestore della richiesta può restituire un oggetto istanza della classe 4D.OutgoingMessage, cioè un contenuto web completo pronto per essere gestito da un browser (ad esempio, il contenuto di un file).
un semplice esempio per iniziare
Con lo stesso file HTTPHandlers.json di cui sopra:
[
{
"class": "GeneralHandling",
"method": "gettingStarted",
"pattern": "start",
"verbs": "get, post"
}
]
La richiesta http://127.0.0.1/start/example?param=demo&name=4D viene eseguita con un verbo GET in un browser. Viene gestita dalla funzione gettingStarted() della classe singleton GeneralHandling di cui sotto:
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 richiesta viene ricevuta sul server come $request (un’istanza dell’oggetto della nuova classe 4D.IncomingMessage ).
Questo oggetto $request contiene le proprietà
- url (String) – URL della richiesta
- urlQuery (Object) – Parametri della richiesta.
- verb (Stringa) – Verbo
- urlPath (collezione di stringhe) – Parti dell’URL della richiesta.
Ecco la risposta:
come gestire un corpo della richiesta
La nuova classe 4D.IncomingMessage fornisce alcune funzioni per ottenere le intestazioni e il corpo della richiesta.
esempio
Eseguiamo un semplice esempio per caricare un file sul server.
Il file HTTPHandlers.json:
[
{
"class": "UploadFile",
"method": "uploadFile",
"regexPattern": "/putFile",
"verbs": "POST"
}
]
Si noti che il modello di URL è fornito come espressione regolare con la proprietà regexPattern.
La richiesta http://127.0.0.1:8044/putFile?fileName=testFile viene eseguita con un verbo POST e un contenuto di file nel corpo.
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
Il nome del file viene fornito come parametro(fileName) nell’URL. Viene ricevuto nell’oggetto urlQuery nella richiesta.
Funzioni per ottenere le intestazioni e il corpo della richiesta
Nell’esempio precedente, si noti la funzione getHeader() che restituisce una determinata intestazione della richiesta. La classe 4D.IncomingMessage offre anche una proprietà headers (Object) contenente tutte le intestazioni della richiesta.
L’intestazione Content-Type fornisce il formato del corpo della richiesta. In questo esempio, vengono gestiti solo i formati pdf e jpeg.
Si notino le funzioni getBlob() e getPicture() sull’oggetto $request. Esse forniscono il contenuto del corpo nel formato appropriato che corrisponde all’intestazione Content-Type.
Per maggiori dettagli su queste funzioni, consultare la documentazione.
È disponibile anche la funzione getText(), che fornisce il corpo della richiesta come stringa (se è stata inviata come stringa).
Se il corpo è stato fornito come rappresentazione JSON valida, la funzione getJSON() ne fornisce la risoluzione con il tipo corretto (ad esempio, Object, Collection, String, …).
gestire il reindirizzamento
Il gestore della richiesta è anche in grado di reindirizzare su una pagina specifica, restituendo un’istanza della classe4D.OutgoingMessage . L’intestazione Location deve essere utilizzata per indicare la pagina su cui effettuare il reindirizzamento.
Il valore di stato HTTP 3xx indica che il client deve intraprendere ulteriori azioni per completare la richiesta.
Eseguiamo questo scenario:
– L’utente può visualizzare tutte le pagine html nella cartella WebFolder/pages una volta autenticato. Finché l’utente non è autenticato, viene reindirizzato a una pagina di autenticazione.
– Se la pagina richiesta non si trova in questa cartella, viene servita una pagina Non trovato.
– Se l’utente chiede una pagina in una sottocartella della cartella /pages, viene servita una pagina Non autorizzato.
Il file 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
Si noti che il gestore della richiesta ha accesso all’oggetto Session che consente una logica di business più complessa (verifica della presenza di alcuni privilegi, utilizzo dell’oggetto condiviso Session.storage ).
Scaricate l’HDI per esercitarvi a gestire le richieste HTTP e non aspettate oltre per entrare nel mondo del progetto proponendo classi e altre potenti funzionalità.