WordPressiä käytetään yllättävän usein tilanteissa, joissa tiedostojen latausta pitää kontrolloida: jäsenalueet, maksulliset sisällöt, digitaaliset tuotteet, dokumentaatiot tai API-avaimilla suojatut resurssit. Tässä kohtaa kuvaan astuu WordPressin sisäinen tiedostojen latauslogiikka, eli niin sanottu download handler.
Kyse ei ole vain siitä, että tiedosto linkitetään media-kirjastosta. Kyse on oikeuksista, suorituskyvystä, tietoturvasta ja välimuistista.
Mitä download handler tarkoittaa WordPressissä
Download handler tarkoittaa mallia, jossa:
-
tiedosto ei ole suoraan julkisesti ladattavissa
-
lataus kulkee WordPressin (PHP:n) kautta
-
jokainen lataus voidaan validoida, lokittaa ja rajoittaa
Käytännössä:
-
käyttäjä pyytää URL:ia
-
WordPress tarkistaa oikeudet
-
PHP lukee tiedoston
-
tiedosto lähetetään HTTP-responsena
Tämä antaa kehittäjälle täyden kontrollin, mutta tuo myös vastuuta.
Miksi et suoraan linkitä tiedostoon
Suora linkki wp-content/uploads-hakemistoon:
-
ohittaa käyttäjätarkistukset
-
toimii vaikka käyttäjä ei olisi kirjautunut
-
on vaikea lokittaa
-
ei mahdollista latausrajoituksia
Download handler:
-
mahdollistaa roolipohjaisen pääsyn
-
tukee kertakäyttöisiä linkkejä
-
estää hotlinkingin
-
mahdollistaa latausmäärien seurannan
Jos tiedostolla on arvoa, sitä ei pidä jakaa suorana URL:ina.
WordPressin perusmekanismit latauksiin
PHP ja HTTP-headerit
Sisäinen lataus perustuu:
-
readfile()taifpassthru() -
oikeisiin HTTP-headereihin
-
output bufferin hallintaan
Tyypillisiä headereita:
-
Content-Type -
Content-Disposition: attachment -
Content-Length -
Cache-Control
Yksikin väärä header voi rikkoa latauksen.
Yksinkertainen latausflow
Tyypillinen rakenne:
-
oma endpoint tai query-parametri
-
oikeustarkistus
-
tiedoston polun resolvointi
-
headerien lähetys
-
tiedoston streamaus
-
exit
Tärkeää on, ettei WordPress ehdi tulostaa mitään muuta ennen tiedostoa.
REST API vs perinteinen download handler
REST API:
-
sopii JSON-datalle
-
ei ole ihanteellinen binääritiedostoille
-
tuo turhaa overheadia
Perinteinen handler:
-
kevyempi
-
suoraviivaisempi
-
helpompi yhdistää selaimen latauslogiikkaan
Useimmissa tapauksissa lataukset kannattaa hoitaa ei-REST-pohjaisesti.
Suorituskyky: PHP ei ole CDN
Suurin sudenkuoppa
Kun PHP:
-
lukee suuria tiedostoja
-
jokaiselle lataukselle erikseen
-
ilman offloadia
se:
-
kuormittaa PHP-FPM:iä
-
hidastaa muita pyyntöjä
-
ei skaalaudu hyvin
Ratkaisu ei ole “enemmän muistia”, vaan arkkitehtuuri.
X-Sendfile ja X-Accel-Redirect
Oikea tapa tehdä tämä oikein
Moderni malli:
-
PHP validoi käyttäjän
-
PHP palauttaa headerin
-
web server toimittaa tiedoston
Apache:
-
X-Sendfile
Nginx:
-
X-Accel-Redirect
Hyödyt:
-
PHP ei streamaa tiedostoa
-
lataus on nopea
-
palvelin kuormittuu vähemmän
-
toimii suurille tiedostoille
Tämä on käytännössä paras ratkaisu tuotantoon.
Tietoturvanäkökulma
Download handlerissa pitää huomioida:
-
polkumanipulaatio (path traversal)
-
mime-tyypin spoofaus
-
pääsyn ohitus suoralla URL:illa
-
nonce- tai token-tarkistus
Älä koskaan:
-
hyväksy käyttäjän syöttämää tiedostopolkua sellaisenaan
-
palauta virheviestejä, jotka paljastavat hakemistorakenteen
Cache ja lataukset
Mikä kannattaa välimuistittaa
Yleensä:
-
latauksia ei cacheteta selaimessa pitkään
-
mutta metadata voidaan cachettaa
-
CDN voi cachettaa itse tiedoston, ei validointia
Jos käytössä on token-pohjainen lataus:
-
token ei saa cacheutua
-
vastaukset pitää merkitä yksilöllisiksi
Download handler ja välimuisti eivät ole automaattisesti ystäviä.
Multisite ja lataukset
Multisite-ympäristössä:
-
media voi olla jaettua
-
käyttäjäoikeudet vaihtelevat
-
domain mapping tuo omat haasteensa
Handlerin pitää:
-
tunnistaa oikea blog_id
-
tarkistaa oikeudet oikein
-
estää tiedostojen vuotaminen sivustojen välillä
Tämä on usein aliarvioitu riski.
Yleisimmät virheet
Tyypillisiä ongelmia:
-
headerit lähetetään liian myöhään
-
output bufferia ei tyhjennetä
-
PHP:n memory_limit ylittyy
-
tiedostoja streamataan PHP:llä turhaan
-
lataukset rikkoutuvat CDN:n takana
Useimmat näistä ovat arkkitehtuurivirheitä, eivät “bugia”.
Milloin WordPressin sisäinen lataus on oikea ratkaisu
Käytä download handleria, kun:
-
tiedostot ovat suojattuja
-
käyttäjäoikeudet ratkaisevat
-
latauksia pitää seurata
-
haluat kontrollin jakeluun
Älä käytä sitä, kun:
-
tiedostot ovat täysin julkisia
-
latauksia on massiivisesti
-
CDN riittää yksinään
Lopuksi: kontrolli maksaa, mutta on sen arvoista
WordPressin sisäinen tiedostojen lataus ei ole ilmainen ratkaisu. Se tuo:
-
lisää koodia
-
lisää vastuuta
-
lisää suunnittelua
Vastineeksi se tuo:
-
tietoturvaa
-
hallittavuutta
-
liiketoiminnallista kontrollia
Hyvin toteutettuna download handler on näkymätön käyttäjälle ja arvokas järjestelmälle.
