Předběžná verze dokumentace ke knihovně filtrů
Předpokládám, že současný model bude změněn z |-> na ->| (viz TODO),
proto považujte tento dokument za zcela nezávazný.

Následující popis je sice zaměřen na filtrování výstupu z modulů Apache, ale popsaný mechanizmus by měl platit pro manipulaci s filtry obecně.

Současná koncepce filtrů umožňuje:

  1. aby si filtry posílaly různé signály,
  2. aby nemusely veškerá data neustále kopírovat z buferu do buferu, tj. aby několik filtrů mohlo sdílet tentýž bufer,
  3. aby se neaktivní filtry mohly samy odstranit z řetězce filtrů, tj. není nutné dávat pozor, aby byly v řetězci jen ty filtry, které budou skutečně při filtrování aktivní.

Výhody filtrů oproti stávajícímu řešení:

  1. Filtry umožní věci, které bez nich nejsou možné nebo by se dělaly velice obtížně (mod_czech, "on fly" compression, ...).
  2. Elegantně nahradí některé části Apache, které jsou teď ošklivě složité a "sdrátované" (chunked encoding, EBCDIC).
  3. Filtry mají modulární strukturu, tudíž se snáze píší, mění a opravují.

Jak to funguje:

Filtry jsou seřazeny do řetězce filtrů. Řetězec filtrů bere při zavolání ze svého vstupu data, prožene je jednotlivými filtry a uloží je na svůj výstup. Činnost filtrů se řídí signály, které jim řetězec posílá, pořadí volání filtrů závisí na hodnotách, které filtry vracejí. Na konci vrátí řetězec filtrů hodnotu, z které je poznat důvod, proč řetězec svoji činnost přerušil nebo ukončil.

Významy signálů jsou následující:

  1. F_INIT dostane filtr jen jednou, a to jako úplně první signál.
    Filtr by se měl při tomto signálu inicializovat, k čemuž může použít i informace uložené v f->fch->*.
    Při inicializaci může filtr např. sám sebe trvale odstranit (funkcí remove_filter() - jako např. filtr f_out_charset, pokud se dokument typu f->fch->r->content_type nebude kódovat); nebo svůj bufer může spojit s buferem následujícího filtru (funkcí attach_filter_buffer() - pokud filtr s většinou dat v buferu nepotřebuje manipulovat, např. f_out_chunk).
    Pozor: Při F_INIT už f->next nemusí mít svůj bufer prázdný!
  2. Je-li filtr zavolán bez signálu, měl by provádět svoji normální funkci, tj. konvertovat data, která bere ze svého vlastního buferu a ukládá v buferu fitru f->next.
    Pozor: Filtr by měl vyprázdnit svůj bufer dříve, než vrátí F_IBE! To, že se filtr dostal ke slovu, znamená, že předchozí filtr už neměl kam dávat data - a dokud filtr svůj bufer neuvolní, pro předchozí filtr se nic nezmění. Nerespektování tohoto doporučení může vyvolat zacyklení řetězce filtrů!
  3. F_RECONF znamená, že se změnily některé parametry, především f->r, a že by se filtr měl připravit na reinicializaci.
    Filtr může signál odmítnout a vrátit F_IBE, ale pokud jej akceptuje, musí svůj bufer i všechny své vnitřní bufery vyprázdnit, a místo F_IBE vrátit F_IBE rozšířené o tentýž signál (totiž F_IBE | F_RECONF) jako potvrzení, že je připraven.
    V případě akceptování signálu a vrácení F_IBE | F_RECONF dostane filtr při příštím zavolání signál F_INIT | F_RECONF.
    Poznámky:
    1. Kromě F_RECONF mohou existovat i jiné signály, které jsou však určeny konkrétním filtrům (např. F_CHARSET). Filtr by se k těmto signálům měl chovat vesměs stejně jako k F_RECONF.
    2. Filtr by měl signál F_RECONF akceptovat, pokud k odmítnutí nemá nějaký zvláštní důvod (např. pokud by vypráznění vnitřních buferů znamenalo ukončení činnosti filtru, jako (asi) u f_compress). Umožní tím reinicializaci i filtrům za ním následujícím, ke kterým by se při odmítnutí signál F_RECONF nedostal.
    3. Vrácením samotného F_RECONF filtr tento signál vyvolá; potvrzení signálu vyžaduje vrátit F_IBE | F_RECONF!
  4. F_INIT | F_RECONF znamená totéž co samotný F_INIT, jen s informací navíc, že není nutné provádět kompletní inicializaci. Filtr může v tuto chvíli např. znovu obnovit připojení svého buferu funkcí attach_filter_buffer(), nastavit si různé parametry apod.
    Pozor: Z f->fch->r by si měl filtr údaje zkopírovat, protože po návratu z subrequestu může být tento pointer neplatný a filtr by tak mohl způsobit segmentation violation. Totéž se týká i ostatních údajů - mohou se změnit ještě před F_RECONF, kdy filtr stále potřebuje znát staré hodnoty.
  5. F_EOF je protipólem F_INIT. Filtr musí svůj bufer a všechny své vnitřní bufery vyprázdnit, a ve chvíli, kdy vrátí F_EOF, jeho činnost končí (už nebude volán).
  6. Na F_ERR by měl filtr reagovat stejně jako na F_EOF, jen místo F_EOF musí vrátit F_ERR.

Podrobněji o signálech:

Pomocná makra:

Poznámky:


Poznámky k filtrování výstupu z Apache: