V dnešním světě založeném na webu servery zpracovávají ohromné množství požadavků. Efektivní analýza, počítání, interpretace a přesměrování těchto požadavků je nezbytné, zejména při použití principů MVC.
Díky zavedení obsluhy požadavků HTTP na serveru 4D HTTP Server můžete spouštět specifickou obchodní logiku na základě přijatých požadavků. Tato výkonná funkce odemyká mnoho možností, jak je podrobně popsáno v tomto příspěvku na blogu.
Pomocí HTTP Request Handlers můžete definovat libovolný počet obslužných rutin přizpůsobených konkrétním vzorům URL a slovesům HTTP. Tento přístup poskytuje mnohem větší granularitu než tradiční databázové metody On Web Authentication a On Web Connection a ušetří vás implementace rozsáhlých příkazů Case of.
Proč obsluhy požadavků?
Obsluha obsluhy požadavků vede k různým scénářům, jako např:
- použití dané adresy URL jako poskytovatele zdrojů (např. stahování různých souborů voláním určité adresy URL)
- použití dané adresy URL jako pole pro nahrávání souborů(např. nahrávání různých souborů voláním určité adresy URL)
- zpracovávat přesměrování na konkrétních stránkách podle obchodního kontextu(např. uživatel ověřen nebo ne, stránka nenalezena, oprávnění udělena nebo ne … atd.)
- uchovávat statistiky a veškeré informace související s přijatým požadavkem.
- zpracovávat ověřování prostřednictvím oAuth 2.0
jak nastavit obsluhu požadavků HTTP
Obsluhy požadavků HTTP musí být nastaveny v souboru HTTPHandlers.json ve složce Project/Sources.
Tento soubor obsahuje kolekci objektů ve formátu JSON. Každý objekt odkazuje na zpracovatele požadavků s následujícími informacemi:
- vzor URL, který se má zpracovat
- sloveso použité v adrese URL
- [singleton třídy + funkce], kde je implementován kód obsluhy požadavku
příklad
Soubor HTTPHandlers.json:
[
{
"class": "GeneralHandling",
"method": "gettingStarted",
"pattern": "start",
"verbs": "get, post"
}
]
Otázka: Co to znamená?
Odpověď: Co to znamená? To znamená, že když je na serveru přijat jakýkoli požadavek začínající /start/ se slovesem GET nebo POST, provede se funkce gettingStarted singletonu GeneralHandling.
Jak implementovat kód obsluhy požadavku
Výše uvedená třída singleton musí být sdílená.
Vstup: instance nové třídy 4D.IncomingMessage.
Požadavek je na serveru přijat jako instance objektu nové třídy 4D.IncomingMessage.
K dispozici jsou následující informace:
- kompletní url adresa požadavku
- části url adresy
- sloveso požadavku
- hlavičky požadavku
- parametry vložené do adresy URL (pokud existují)
- tělo požadavku (pokud existuje)
Obsluha požadavku pak může všechny tyto informace použít ke spuštění příslušné obchodní logiky.
Výstup: instance třídy 4D.OutgoingMessage
V případě potřeby může obsluha požadavku vrátit instanci objektu třídy 4D.OutgoingMessage, , tj. nějaký úplný webový obsah připravený pro zpracování prohlížečem(např. jako obsah souboru).
jednoduchý příklad pro začátek
Se stejným souborem HTTPHandlers.json jako výše:
[
{
"class": "GeneralHandling",
"method": "gettingStarted",
"pattern": "start",
"verbs": "get, post"
}
]
http://127.0.0.1/start/example?param=demo&name=4D je v prohlížeči spuštěn požadavek se slovesem GET. Je zpracován níže uvedenou funkcí gettingStarted() singletonové třídy GeneralHandling:
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
Požadavek je na serveru přijat jako $request (instance objektu nové třídy 4D.IncomingMessage ).
Tento objekt $request obsahuje vlastnosti:
- url (String) – adresu URL požadavku
- urlQuery (Object) – parametry požadavku.
- verb (String) – Sloveso
- urlPath (kolekce řetězců) – části URL požadavku
Zde je odpověď:
jak zpracovat tělo v požadavku
Nová třída 4D.IncomingMessage poskytuje několik funkcí pro získání hlaviček a těla požadavku.
Příklad:
Spusťme jednoduchý příklad pro nahrání souboru na server.
Soubor HTTPHandlers.json:
[
{
"class": "UploadFile",
"method": "uploadFile",
"regexPattern": "/putFile",
"verbs": "POST"
}
]
Všimněte si, že vzor URL je zadán jako regulární výraz pomocí vlastnosti regexPattern.
Požadavek http://127.0.0.1:8044/putFile?fileName=testFile je spuštěn se slovesem POST a obsahem souboru v jeho těle.
Třída UploadFile singleton:
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
Název souboru je uveden jako parametr(fileName) v adrese URL. Je přijat v objektu urlQuery v požadavku.
Funkce pro získání hlaviček a těla požadavku
Ve výše uvedeném příkladu si všimněte funkce getHeader(), která vrací danou hlavičku požadavku. Třída 4D.IncomingMessage nabízí také vlastnost headers (Object), která obsahuje všechny hlavičky požadavku.
Hlavička Content-Type udává formát těla přijatého požadavku. V tomto příkladu jsou zpracovány pouze formáty pdf a jpeg.
Všimněte si funkcí getBlob() a getPicture() na objektu $request. Ty poskytují obsah těla v příslušném formátu, který odpovídá hlavičce Content-Type.
Další podrobnosti o těchto funkcích najdete v dokumentaci.
K dispozici je také funkce getText(), která poskytuje tělo požadavku jako řetězec (pokud byl odeslán jako řetězec).
Pokud bylo tělo předáno jako platná reprezentace JSON, funkce getJSON() poskytne jeho rozlišení se správným typem (např. Object, Collection, String, …).
zvládnout přesměrování
Obsluha požadavku je také schopna přesměrovat na konkrétní stránku tak, že vrátí instanci třídy4D.OutgoingMessage . K označení stránky, na kterou se má přesměrovat, je třeba použít hlavičku Location.
Hodnota stavu HTTP 3xx označuje, že klient musí provést další akci k dokončení požadavku.
Spusťme tento scénář:
– Uživatel si po ověření může prohlédnout všechny html stránky ve složce WebFolder/pages . Dokud uživatel není ověřen, je přesměrován na stránku pro ověření.
– Pokud se požadovaná stránka v této složce nenachází, zobrazí se stránka Nenalezeno.
– Pokud se uživatel ptá na stránku v podsložce složky /pages, zobrazí se stránka Neautorizováno.
Soubor HTTPHandlers.json:
[
{
"class": "PagesHandling",
"method": "handle",
"regexPattern": "/pages/"
}
]
PagesHandling singleton třídy:
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
Všimněte si, že obsluha požadavku má přístup k objektu Session, který umožňuje složitější obchodní logiku (kontrola přítomnosti některých oprávnění, použití sdíleného objektu Session.storage ).
Stáhněte si HDI, abyste si procvičili obsluhu požadavků HTTP, a nečekejte více, až vstoupíte do světa projektového režimu navrhování tříd a dalších výkonných funkcí.