V dnešnom blogu pre predstavu opíšem ako funguje klasický routing a uploadovanie súborov.

Časť 2: Ako funguje Total.js na pozadí
Ak Vás zaujala časť 1, tak určite Vás zaujme aj táto časť 2. V tejto časti sa pozrieme na spracovanie dynamického obsahu a na uploadovanie súborov.
Routing
Trasovanie (routing) považujem asi za najdôležitejšiu časť frameworku, pretože registrovaním (vytvorením) trasy vzniká webová aplikácia. Total.js pozná 3x rôzne typy trás:
- dynamický obsah:
F.route(), príklad:/products/ - súbory:
F.file(), príklad:/img/logo.png - websocket:
F.websocket()príklad:/chat/
Framework vyhodnocuje trasovanie pre každý typ requestu trošku inak. Pri prijatí requestu vyhodnotí framework, či sa jedná o súbor (kontroluje či má .extension - koncovku) a ak platí, že sa jedná o súbor, tak request ďalej spracúva tzv. FileHandler - (spracovanie statických súborov), v opačnom prípade sa request začne analyzovať ako dynamický obsah:
- Total.js sa snaží vyparsovať z requestu tzv.
flagsnapr.xhr,mobile,robot,post,put, atď. - následne sa overí podľa
Content-Type, či request obsahuje binárne data
Pokiaľ obsahuje request.method: GET, HEAD alebo OPTIONS
Tento typ requestu je spracovaný najrýchlejšie, pretože neobsahuje žiadne data v tele requestu, ktoré je potrebné dodatočne parsovať. Takže framework vyhodnotí:
- vyhodnotí sa CORS
- globálny middleware (ak je)
- vyhodnotí sa autorizácia (ak je)
- vyhodnotí sa trasovanie
- vyhodnotí sa route middleware (ak je)
- vytvorí sa inštancia controllera
- spustí sa akcia s scope controllera
Request s content-type: application/x-www-form-urlencoded alebo iným
Pri zistení, že sa jedná o tento typ requestu, tak framework vyhľadá trasu route a podľa jej nastavenia začne načúvať udalosť request.on('data'). Ak trasa neexistuje, framework vracia 403 a žiadne data nepríjma.
Ak trasa existuje tak do dočasnej premennej req.buffer_data začne framework postupne zapisovať prijaté data po chunk (rozumej pole bytes), veľkosť prijatých dát (default: 5 kB) závisí od povolenia v metóde F.route() (túto veľkosť je možné zmeniť celoplošne aj v configu). Ako náhle veľkosť prekročí stanovený limit:
- framework ruší príjmanie dát a maže obsah
req.buffer_datapre vyčistenie pamäti - následne je clientovi vrátená chyba
431: Request Header Fields Too Large
V prípade, že data sú OK, tak sa vyhodnocuje:
- data sa deserializujú (
JSON to Object,UrlEncoded to Object,Xml to Objectalebo ostávajúraw) - ak trasa obsahuje mapovanie na schému, tak data sa predpripravia a validujú podľa schémy
- ďalej sa vykoná authorizácia (ak je)
- vyhodnotí route middleware (ak je)
- vytvorí sa inštancia controllera
- spustí sa akcia v rámci scope controllera
Request s content-type: multipart/form-data
Uploadovanie súborov je v Total.js dosť špecifické kvôli 2 veciam (o tom neskôr). Na spracovanie uploadu používam algoritmus node-formidable, ktorý používa ak sa nemýlim aj framework Express.js. V každom prípade, nejdem písať o tom ako funguje tento algoritmus, ale ako Total.js rieši problémy s uploadovaním súborov a čo všetko k tomu ešte navyše ponúka.
Upload súborov funguje tak, že všetky súbory v requeste sa automaticky ukladajú do temporary adresára /myapp/tmp/. Framework pri zisťovaní obsahu requestu a zistení, že sa jedná o súbor otvorí Writable Stream pre každý súbor a prijaté data po chunk (rozumej pole bytes) zapisuje do súboru. Celý tento proces je streamovaný a neblokuje vlákno. V prípade, že sa jedná o obrázok, tak framework sa snaží na základe content-type súboru zistiť jeho rozmery v prvom chunk. Pri gif, png a svg je rýchlo čitateľné rozlíšenie obrázku, no a pri jpg je ten proces trošku náročnejší. Takže prvou špecifickou vecou v Total.js je to, že Total.js Vám pri uploade obrázkov ihneď zistí ich rozlíšenie (toto správanie sa dá vypnúť cez tzv. Total.js behaviour). Ostatné data (nie binárne) sú spracované klasicky ako pri content-type application/x-www-form-urlencoded.
Druhou špecifickou vecou pri uploade súborov je to, že Total.js počíta veľkosť aktuálne zapísaných dát, takže sa nemôže stať, že Vám niekto začne uploadovať 1 GB data a tým zaťažovať server. By default je veľkosť nastavená na 5 kB a pri každej F.route() si viete túto veľkosť zmeniť:
Po dokončení príjmania dát sa:
- data sa deserializujú (
UrlEncoded to Object) - ak trasa obsahuje mapovanie na schému, tak data sa predpripravia a validujú podľa schémy
- ďalej sa vykoná authorizácia (ak je)
- vyhodnotí route middleware (ak je)
- vytvorí sa inštancia controllera
- spustí sa akcia v rámci scope controllera
Framework vymaže všetky nahraté súbory automaticky, keď sa ukončí response. Toto správanie sa dá tiež vypnúť cez controller.noClear(true), len potom je potrebné vymazať data manuálne cez controller.clear() alebo req.clear().
WebSocket
O WebSocket budem písať v inom blogu, ktorý sa mu bude samostatne venovať. Len pre informovanosť uvediem, že spracovanie WebSocketu funguje trošku inak.
Zaujímavosti
Query argumenty:
req.query / controller.query vlastnosť je parsovaná len vtedy, keď sa volá. Výsledky parsera sú následne uložené do skrytej property a pri opätovnom volaní sa už hodnoty znova neparsujú.
Vyhodnotenie trás je cacheované:
Vyhodnotenie trás a ich flagov sa cachuje. To znamená, že framework sa snaží zapamätať zapamätateľné trasy, tak - aby pri nasledujúcom requeste nemusel prehľadávať všetky trasy znova.
CORS:
CORS mechanizmus sa vyhodnocuje ihneď v prípade OPTIONS metódy a ďalej framework vo vyhodnocovaní nepokračuje. Napísal som ho tak, aby bol čo najefektívnejší. Framework obsahuje F.cors() metódu na povolenie CORS, viac v dokumentácii.
Flagy robot a referer:
Sú analyzované len vtedy, ak framework obsahuje reálne routes s týmito flagmi. ... aj takto som sa snažil šetriť performance.
Timeouty:
Zaujímavou funkciou v Total.js sú timeouty. Pokiaľ controller neodpovie v požadovanom čase, napr. stane sa neočakávaná chyba, framework jednoducho request ukončí. Toto správanie sa dá vypnúť alebo upraviť jeho čas priamo pri vytváraní trasy F.route(). Viac info v dokumentácii.
Dynamicky definované argumenty:
Dynamicky definované argumenty v trasovaní sa nevyhodnocujú nijako špeciálne. Framework vidí dynamické hodnoty takto /products/{0}/{1}/{2}/ a my ich deklarujeme napr. takto /products/{category}/{subcategory}/{detail}/ takže v konečnom dôsledku ich v akcii môžeme nazvať ako chceme, viď nižšie uvedený príklad:
Other posts from Peter Širka
- 2025-08-08Recenzia Sigma 500mm F5.6 L-Mount
- 2025-07-21Export obrázkov - Lightroom vs Luminar Neo
- 2025-01-13Recenzia full frame fotoaparátu Lumix S5II
- 2024-10-30JavaScript na serveri rýchlo a jednoducho so slovenským Total.js frameworkom
- 2024-02-18Ako lietať s long range dronom?
- 2024-02-09Recenzia drona DJI FPV
- 2024-02-07Recenzia drona DJI Avata
- 2023-01-06Ako spustiť Total.js framework?
- 2023-01-03Inštalácia Node.js + vysvetlenie použitia modulov
- 2022-05-26Základné informácie o Total.js Platforme
