Implementace prevodu HTML na PDF
Sluzba prijme adresu HTML dokumentu nebo HTML v tele requestu a vrati PDF. Navrzena pro dokumenty o stovkach az tisicich stranek. Rendering: - WeasyPrint jako vychozi engine, spravne CSS Paged Media, nizka pametova narocnost, bez JavaScriptu - Chromium pres Playwright pro dokumenty dokreslovane skripty - rezim auto s detekci skriptu a fallbackem pri selhani WeasyPrintu Velke dokumenty: - deleni na casti na strukturalnich hranicich, rez nikdy uvnitr tabulky nebo odstavce - dvoupruchodovy render obsahu se skutecnymi cisly stranek, pozice nadpisu se ctou z kotev hlasenych u kazde stranky - cislovani stranek bud pres CSS countery, nebo pres cislovaci vrstvu nastampovanou na hotove PDF, rozmer stranky se cte z vysledneho souboru - Chromium se restartuje po N jobech, nikdy vsak behem beziciho renderu API: - POST /convert synchronne, POST /jobs asynchronne se sledovanim stavu, stahovanim vysledku, rusenim a volitelnym callbackem - GET /health s overenim dostupnosti obou enginu a stavem fronty - OpenAPI respektuje prefix reverse proxy pres root_path Bezpecnost a provoz: - SSRF kontrola po DNS resolvu, na kazdem presmerovani a u vsech pozadavku prohlizece - nedostupne assety render nezastavi, ale hlasi se v odpovedi i v logu - fronta s omezenym poctem workeru, rozpracovane joby se pri ukonceni oznaci jako failed, nezmizi potichu - strukturovane JSON logovani s job_id - vsechny limity vypnute ve vychozim stavu Dockerfile je dvoufazovy, obsahuje zavislosti WeasyPrintu, Chromium a fonty s ceskou diakritikou. Autentizace zamerne neni implementovana, zpusob predavani neni domluveny. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
e3cc8f418b
commit
156289fe2d
@@ -0,0 +1,100 @@
|
||||
# Provoz
|
||||
|
||||
## Docker image
|
||||
|
||||
Image je dvoufazovy. Prvni faze stavi zavislosti, do vysledneho image se
|
||||
prekladace nedostanou.
|
||||
|
||||
Runtime obsahuje:
|
||||
|
||||
- systemove knihovny WeasyPrintu: cairo, pango, gdk-pixbuf, harfbuzz
|
||||
- Chromium nainstalovany pres `playwright install --with-deps chromium`
|
||||
- fonty DejaVu, Liberation a Noto vcetne ceske diakritiky
|
||||
- `qpdf` jako zaloha pro praci s PDF
|
||||
- `curl` pro healthcheck
|
||||
|
||||
Image je velky, radove jednotky GB. To je u sluzby, ktera v sobe ma cely
|
||||
prohlizec a dve renderovaci knihovny, ocekavane.
|
||||
|
||||
## Port
|
||||
|
||||
Sluzba posloucha na `0.0.0.0:8000`, coz odpovida `app.yml`. Port se nemeni bez
|
||||
odpovidajici upravy metadat aplikace v AppFactory.
|
||||
|
||||
## Healthcheck
|
||||
|
||||
Dockerfile ma `HEALTHCHECK`, ktery vola `/health` na `127.0.0.1:8000`.
|
||||
Endpoint pri kazdem volani overuje dostupnost enginu vcetne skutecneho
|
||||
nastartovani Chromia.
|
||||
|
||||
## Sdilena pamet pro Chromium
|
||||
|
||||
Chromium se spousti s `--disable-dev-shm-usage`, takze si vystaci s malym
|
||||
`/dev/shm`. Pokud by se v logu objevovaly pady rendereru, je potreba containeru
|
||||
zvysit `--shm-size`.
|
||||
|
||||
## Overeni po nasazeni
|
||||
|
||||
```bash
|
||||
curl -i https://services.csbot.cz/apps/html-to-pdf/health
|
||||
curl -i https://services.csbot.cz/apps/html-to-pdf/docs
|
||||
```
|
||||
|
||||
Ve Swagger UI overit, ze Try it out vola adresy s prefixem
|
||||
`/apps/html-to-pdf`, ne bez nej.
|
||||
|
||||
Pozor na znamou vlastnost AppFactory: Caddy propousti GET pozadavky jen
|
||||
z omezeneho seznamu IP adres. Try it out ve Swaggeru proto muze z bezneho
|
||||
prohlizece vracet 403 jako `text/plain`, i kdyz je sluzba v poradku. Overovat
|
||||
curlem primo ze serveru.
|
||||
|
||||
## Logy
|
||||
|
||||
Kazdy zaznam je jeden radek JSON. Vsechno, co patri k jednomu jobu, nese
|
||||
`job_id`.
|
||||
|
||||
Co stoji za sledovani:
|
||||
|
||||
- `Asset could not be loaded` v PDF neco chybi
|
||||
- `WeasyPrint render failed, falling back to Chromium` dokument neprosel
|
||||
primarnim enginem
|
||||
- `Restarting Chromium to release memory` bezna udrzba, ne chyba
|
||||
- `Callback could not be delivered` job dobehl, ale klient se to nedozvedel
|
||||
- `Job failed` konverze selhala, kod chyby je v poli `error_code`
|
||||
|
||||
Secrets se do logu nezapisuji.
|
||||
|
||||
## Znama omezeni
|
||||
|
||||
- Fronta je v pameti procesu. Restart znamena ztratu rozpracovanych jobu, ty se
|
||||
oznaci jako failed s kodem `service_restarted`.
|
||||
- Obsah s cisly stranek umi jen WeasyPrint. Chromium neumi rict, na ktere
|
||||
strance nadpis skoncil.
|
||||
- U cleneneho dokumentu nejsou odkazy v obsahu klikatelne, protoze cil lezi
|
||||
v jine casti souboru. Cisla stranek jsou spravna a sluzba na to upozorni ve
|
||||
`warnings`.
|
||||
- Slucovani pres pypdf drzi stranky vysledku v pameti. Je to nejnarocnejsi krok
|
||||
konverze.
|
||||
- WeasyPrint nespousti JavaScript. Pro dokumenty dokreslovane skripty je nutne
|
||||
Chromium.
|
||||
|
||||
## Testy
|
||||
|
||||
Testy se spousti jen na vyslovne pozadani, nikdy automaticky.
|
||||
|
||||
```bash
|
||||
pip install -r requirements-dev.txt
|
||||
pytest # bez pomalych testu spusti vse ostatni
|
||||
pytest -m slow # jen mereni nad dokumentem o zhruba 1200 strankach
|
||||
```
|
||||
|
||||
Testy, ktere potrebuji WeasyPrint, se same preskoci, pokud neni nainstalovany.
|
||||
|
||||
Co je pokryte:
|
||||
|
||||
- SSRF vcetne domeny mirici na 127.0.0.1
|
||||
- deleni dokumentu, ktery se delit da, i toho, ktery se delit neda
|
||||
- spravnost cisel stranek po slouceni
|
||||
- obsah ukazuje na skutecne stranky
|
||||
- nedostupny asset render nezastavi a objevi se v odpovedi
|
||||
- zruseni beziciho jobu, plna fronta, chovani pri ukonceni sluzby
|
||||
Reference in New Issue
Block a user