Ari Rantala -> Oppaat -> Apache
Web-palvelin: muistiinpanot
1 . Yleistä
- Webissä (HTTP-protokolla) tapahtuva digitaalinen
vallankumous -> Web-palvelimet merkittävimpiä
palvelinsovelluksia
- "Uudet" laajennokset esim. WebDAV korostavat merkitystä
- Apache merkittävin Linuxin päällä
ajettava palvelinsovellus
- Apachen "markkinaosuus" noin 35% <URL: http://news.netcraft.com/archives/web_server_survey.html
> (2015)
Apache Software Foundationin (ASF)
Apache-projektin kehittämän Apache web-palvelimen
kehitystyö aloitettiin
maaliskuussa 1995. Apachen ensimmäinen versio pohjautui sen hetken
käytetyimmän web-palvelimen, eli NCSA 1.3 palvelimen
lähdekoodiin.
Apachen nimi tulee sanoista "A PAtCHy server" (paikattu palvelin),
koska
se perustui valmiiseen NSCA-koodiin sekä siihen tehtyihin
korjauksiin
eli paikkoihin (eng. patch). Apache on ollut vuosia selkeästi
käytetyin
web-palvelinohjelmisto. Apache on ilmainen ja sen lähdekoodi on
avoin.
1.1 Apachen ominaisuudet tiivistettynä
- Tehokas
- Tietoturvallinen
- Saatavilla lähdekoodeineen ilmaiseksi
- Muokattavissa hyvin moniin
käyttötarkoituksiin
- Uusien
moduulien lisääminen ja Apachen toiminnan laajentaminen
mahdollista.
- Graafiset työkalut hallinnointiin ovat vaatimattomia.
Apache on perinteisesti
haarauttanut (fork) palvelinprosessinsa
haluttuun määrään lapsiprosesseja etukäteen
(prefork). Tätä "prefork"-mallia käytetään
kaikissa Apache 1.x -sarjan palvelimissa sekä oletuksena
uudemmissa 2.x -sarjan Unix- ja Linux-versioissa. Näitä
lapsiprosesseja pidetään aina käynnissä vapaana
(idle) alustustiedostoissa määrätty
määrä. Asiakkailta (yleensä selaimelta) tuleviin
HTTP-pyyntöihin vastaavat juuri
nämä httpd-lapsiprosessit. Näin ollen palvelinprosessin
käynnistykseen ei kulu aikaa pyynnön tapahtuessa. Jokaista
HTTP-pyyntöä
palvelee oma prosessi. Kun palvelevien httpd-prosessien
määrä
lisääntyy, Apache käynnistää yhä uusia
vapaita
prosesseja odottamaan pyyntöjä.
Linuxissa prosessien käsittely on tehokasta, mutta joissakin
järjestelmissä menettely heikentää
suorituskykyä kuorman (pyyntöjen) kasvaessa. Apache 2 tarjoaa
"prefork"-menetelmän lisäksi käytettäväksi nk.
"worker"-menetelmää, jossa yksi lapsiprosessi voi
säikeiden avulla käsitellä useita pyyntöjä.
Väitetään, että Apache 2:n suorituskyky on
huomattavasti parempi verrrattuna versioihin 1.3 erityisesti
Windows-järjestelmissä.
1.2 HTTP-protokolla - Yleistä
HTTP (HyperText Transfer Protocol)
on Web-asiakkaan ja
-palvelimen keskinäiseen tiedonsiirtoon käyttämä
yhteyskäytäntö. Standardoitua
käytäntöä tarvitaan, että eri valmistajien
palvelin- ja asiakasohjelmistot olisivat yhteensopivia
keskenään. Käytettyjä versioita ovat HTTP 1.0 ja
protokollan uusin versio HTTP 1.1 Nimestään huolimatta
HTTP-protokolla ei rajoitu pelkästään HTML-dokumenttien
siirtämiseen. Käytännössä sillä voi
siirtää monenlaista dataa. Palvelin kertoo yleensä
oikein konfiguroituna siirrettävän datan tyypin Content-Type-otsakkeessa.
1.3 HTTP-siirtotapahtuma
Web-palvelin kuuntelee Web-asiakkaiden asiakaspyyntöjä
valitussa portissa. HTTP-siirtotapahtuma alkaa
siitä, kun Web-palvelin saa asiakkaalta pyynnön. Web-palvelin
käsittelee sen ja normaalisti palauttaa selaimelle datan.
Selain yrittää sitten esittää saadun datan parhaan
kykynsä mukaan.
HTTP-siirtotapahtuma koostuu kahdesta HTTP-viestistä
(HTTP message), jotka ovat:
- Asiakaspyyntö (HTTP request), jonka
sisältönä on
- Pyyntörivi (Request-Line)
- HTTP-otsakkeet
- Data
- Palvelimen vastaus (HTTP response), jonka
sisältönä on
- Tilarivi (Status-Line)
- HTTP-otsakkeet
- Data
Asiakaspyyntö
HTTP-asiakaspyyntö etenee seuraavassa muodossa
- Asiakas ottaa yhteyden halutun palvelimen tiettyyn porttiin
(yleensä 80)
- Asiakas lähettää HTTP-komennon
(pyyntörivi), jonka kolmesta välilyönnillä
erotetusta kentästä löytyy
- käytettävä metodi
- pyydettävä dokumentti
- HTTP:n versio
Esimerkki:
GET /manual/ HTTP/1.0
- Asiakas lähettää mahdolliset HTTP-otsakkeet
riveittäin. Kukin rivi koostuu otsakkeen nimestä,
kaksoispisteestä,
välilyönnistä ja otsakkeen arvosta
ja rivinvaihtomerkistä (CRLF). Esimerkiksi
Web-selain voi kertoa näin nimensä,
hyväksymänsä dokumenttityypit, toivomansa kielen jne.
Esimerkki:
User-Agent: Mozilla/3.01Gold (Win95;
I)
Accept: image/gif, image/jpeg jne.
Accept-Language: fi
- Asiakas lähettää rivinvaihtomerkin (CRLF
~
tyhjä rivi)
- Asiakas voi lähettää muuta
dataa. Näin tapahtuu esimerkiksi silloin, kun Web-selain
lähettää HTML-lomakkeen sisältämän datan
POST-metodilla.
- Pyyntö päättyy kahteen
peräkkäiseen rivinvaihtomerkkiin. Jos tämä
tehdään jo otsakkeiden lähettämisen jälkeen
kohdassa 4, niin kohdan 5 muuta dataa ei tällöin
lähetetä.
Palvelimen vastaus
Kun asiakas on lähettänyt HTTP-pyynnön,
palvelin vastaa siihen. Palvelimen vastaus etenee seuraavassa muodossa:
- Palvelin vastaa tilarivillä, jonka kolmesta
välilyönnillä erotetusta kentästä löytyy
- HTTP:n versio
- tilakoodi
- tilakoodin tekstimuotoinen selitys
Tyypillisesti onnistuneeseen pyyntöön vastataan:
HTTP/1.0 200 OK
- Palvelin (tai palvelinskripti) lähettää
mahdolliset HTTP-otsakkeet riveittäin. Kukin rivi koostuu
otsakkeen nimestä, kaksoispisteestä,
välilyönnistä ja otsakkeen arvosta ja rivinvaihtomerkistä
(CRLF). Tyypillisesti voidaan kertoa esimerkiksi
vastauksen luontiaika, tietoja palvelimesta ja palautettavan dokumentin
sisältötyyppi.
Date: Mon, 08 Oct 2007 18:47:01 GMT Server: Apache/2.0.54 (Fedora) Content-Type: text/html
- Palvelin lähettää rivinvaihtomerkin (CRLF
~
tyhjä rivi)
- Pyynnön onnistuessa vastaukseksi
lähetetään mahdollisesti haluttu data, joka voi olla
esimerkiksi
- staattinen tiedosto: HTML-dokumentti, kuvatiedosto,
Excel-asiakirja, zip-tiedosto jne.
- PHP-skriptin generoima HTML-dokumentti, kuvatiedosto
jne.
Huomioita
HTTP on tilaton protokolla. Peräkkäisten
siirtotapahtumien välillä ei ole
mahdollista pitää tilatietoa protokollan avulla.
- Tapahtumien seuranta ei kuormita HTTP:tä.
- Jokainen tapahtuma aloitetaan alusta.
- Web-sovellusten ohjelmointi hankalaa
Mainittakoon erikseen, että HTTP 1.1-protokolla
mahdollistaa yhteyden pitämisen auki, vaikka siirtotapahtuma on
ohi. Näin varsinaista yhteyttä ei tarvitse muodostaa
uudelleen lisäpyyntöjä varten. Tämä nopeuttaa
tavanomaisten HTML-dokumenttien siirtoa, koska ne
sisältävät yleensä HTML-koodin lisäksi useita
kuvia. Tällöin dokumentti kaikkine kuvineen voidaan
mahdollisesti siirtää yhdellä ainoalla
HTTP-yhteydellä. Tässäkin tapauksessa jokainen
dokumenttiin kuuluva tiedosto siirrettään käyttäen
omaa HTTP-siirtotapahtumaa. HTTP 1.0-protokollan tapauksessa asiakkaan
on lähetettävä otsake Connection:
Keep Alive,jotta palvelin pitäisi yhteyden auki
siirtotapahtuman jälkeen.
1.4 Esimerkkejä HTTP-siirtotapahtumista
Tässä kappaleessa esitetään
HTTP-siirtotapahtumia lähinnä pääteyhteydellä
emuloiden. Näissä esimerkeissä Web-selaimen normaalisti
muodostoma asiakaspyyntö kirjoitetaan käsin. Asiakasohjelmana
toimivaksi pääteohjelmaksi sopii mikä tahansa
telnet-ohjelma. Pääteohjelmalla voi keskustella
HTTP-protokollan mukaisesti ottamalla aluksi yksinkertaisesti
yhteyttä Web-palvelimen TCP-porttiin. Kokeiltaessa
esimerkkejä ne eivät välttämättä
toimi täysin samoin. Tämä johtuu esimerkiksi siitä,
että
käytettävä Web-palvelimen konfiguraatio saattaa olla
testaushetkellä
hieman erilainen.
Esimerkki: HTTP/1.1
Kirjoitetaan esim. Linuxin komentoriviltä komento telnet netisto.fi 80, jolla
avataan
yhteys käytettävän palvelimen porttiin 80.
IP-numeron ja portin tilalla voi olla minkä tahansa julkisenkin
Web-palvelimen tiedot. Yhteyden syntymisen merkiksi telnet-ohjelma
tulostaa kolme riviä ja palvelin jää odottamaan,
mitä asiaa asiakkaalla on. HTTP-protokollan mukaisesti ensin on
lähetettävä pyyntörivi. Tässä tapauksessa
pyydetään Web-palvelimen juurihakemistosta dokumenttia index.htm.
Tässä
esimerkissä
HTTP-otsakkeita ja dataa ei lähetetä.
Asiakaspyyntö kuitataan toisellakin rivinvaihdolla, jolloin
Web-palvelin vastaa standardin mukaisesti tilarivillä,
HTTP-otsakkeilla ja varsinaisella datalla. Lopulta yhteys katkaistiin
automaattisesti. Tästä kaikesta tavallinen Web-selailija
yleensä näkee vain muotoillun data-osan eli varsinaisen
HTML-dokumentin.
Host-otsake on
pakollinen HTTP/1.1-protokollab versiossa:
$ telnet netisto.fi 80 Trying 217.30.180.57... Connected to netisto.fi. Escape character is '^]'. GET /index.php HTTP/1.1 Host: netisto.fi
HTTP/1.1 200 OK Date: Mon, 08 Oct 2007 18:47:01 GMT Server: Apache/2.0.54 (Fedora) Last-Modified: Mon, 28 May 2007 04:44:18 GMT ETag: "f60b3e-17ec-66da4c80" Accept-Ranges: bytes Content-Length: 6124 Connection: close Content-Type: text/html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>Ari Rantala: Etusivu</title ...
Connection closed by foreign host.
Samaa esimerkkiä voi kokeilla (hieman
työläämmin) Windowsin telnetillä seuraavasti:
- Käynnistä/Suorita
- kirjoitetaan Avaa-kenttään esim. telnet joku.ip.numero 80
- valitaab Terminal/Preferences ja valitse Local Echo, jotta
kirjoittamasi tekstit näkyisivät
- kirjoitetaan ylimmälle riville pyyntösi
esim. GET /hello.htm HTTP/1.0, jossa
haettavan dokumentin voi valita palvelinkohtaisesti.
- hyväksytään pyyntö kahdella
rivinvaihdolla.
Esimerkki: HTTP/1.1 / Palvelimen aikakatkaisu
Jotkin "isommat palvelimet" katkaisevat HTTP-siirtotapahtuman, jos
asiakas ei saa esitettyä pyyntyä kokonaisuudessaan tietyn
ajan kuluessa TCP-yhteyden aukaisemisesta. Kokeile esim. osoitteeseen
www.intel.com. Kirjoita pyyntörivi kokonaisuudessaan, paina ENTER ja jää hetkeksi
odottelemaan:
$ telnet www.intel.com 80 Trying 217.212.252.145... Connected to www.intel.com. Escape character is '^]'. GET / HTTP/1.1
HTTP/1.0 408 Request Time-out Server: AkamaiGHost ...
The server timed out while waiting for the browser's request.<P> ... Connection closed by foreign host. $
Esimerkki uudelleenohjauksesta
Tässä esimerkissä palvelimen vastaus on 301
Moved Permanently. HTTP-otsakkeissa lähetetään palvelun
uusi
sijainti Location: http://netisto.fi/ottelu/ Vaikka mukana
seuraa asiasta tavanomainen HTML-sivukin, niin yleisimmät selaimet
eivät sitä näytä, vaan siirtyvät
(lähettävät pyynnön) otsakkeen perusteella suoraan
uuteen osoitteeseen.
$ telnet netisto.fi 80 Trying 217.30.180.57... Connected to netisto.fi. Escape character is '^]'. GET /ottelu HTTP/1.1 Host: netisto.fi
HTTP/1.1 301 Moved Permanently Date: Mon, 08 Oct 2007 18:56:21 GMT Server: Apache/2.0.54 (Fedora) Location: http://netisto.fi/ottelu/ Content-Length: 309 Connection: close Content-Type: text/html; charset=iso-8859-1
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>301 Moved Permanently</title> </head><body> <h1>Moved Permanently</h1> <p>The document has moved <a href="http://netisto.fi/ottelu/">here</a>.</p> <hr> <address>Apache/2.0.54 (Fedora) Server at netisto.fi Port 80</address> </body></html> Connection closed by foreign host.
Esimerkki: HEAD-metodi
Pyyntömetodina voi olla HEAD. Tällöin palvelin
ei lähetä dataa, vaan ainoastaan tilarivin ja HTTP-otsakkeet.
Kokeile:
HEAD / HTTP/1.1
Esimerkki: POST-metodi
Viimeisessä esimerkissä havainnollistetaan
POST-metodia. Data-alueessa syötetään nimi-arvo-parina "abc=123&def=456", joka lomakkeen
tapauksessa tarkoittaisi sitä, että esim. abc-nimiseen
tekstinsyöttökenttään olisi kirjoitettu arvoksi
"123" ja def-nimiseen kenttään "456".
$ telnet netisto.fi 80
Trying 217.30.180.57 ...
Connected to netisto.fi.
Escape character is '^]'.
POST /nayta-http-data.php HTTP/1.1
Host: netisto.fi
Content-type: application/x-www-form-urlencoded
Content-length: 15
Connection: close
abc=123&def=456
HTTP/1.1 200 OK
Date: Sun, 26 Sep 2012 17:09:19 GMT
Server: Apache
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html
cb
<h3>HTTP-otsakkeet</h3>
<li>HTTP_CONNECTION = close</li>
<li>HTTP_HOST = netisto.fi</li>
<h3>GET-metodilla saapunut data</h3>
<h3>POST-metodilla saapunut data</h3>
<li>abc = 123</li>
<li>def = 456</li>
0
Connection closed by foreign host.
$
Asianomaisen datan näyttää skripti nayta-http-data.php ,
jonka
ohjelmalistaus on alla. Skriptin toiminnan ymmärtäminen
ei ole tässä vaiheessa tarpeellista.
<?php
header('Content-type: text/html');
echo "<h3>HTTP-otsakkeet</h3>\n"; foreach($_SERVER as $h=>$v) if(ereg('HTTP_(.+)',$h,$hp)) echo "<li>$h = $v</li>\n";
echo "<h3>GET-metodilla saapunut data</h3>\n"; foreach($_GET as $h=>$v) echo "<li>$h = $v</li>\n";
echo "<h3>POST-metodilla saapunut data</h3>\n"; foreach($_POST as $h=>$v) echo "<li>$h = $v</li>\n";
?>
1.5 HTTP-otsakkeiden ja tilakoodien ryhmittelystä
HTTP-otsakkeet ryhmitellään
käyttötarkoituksensa mukaan:
- yleisiin otsakkeisiin, jotka ovat yhteisiä asiakkaalle
ja palvelimelle. Esim:
- Cache-Control: no-cache
Pyyntö olla tallentamatta dokumenttia (data) välimuistiin.
- Connection: close
Asiakas tai palvelin haluaa lopettaa yhteyden.
- Dataotsakkeisiin, jotka antavat informaatioita pyynnön
tai vastauksen dataosasta.
- Asiakkaan pyyntöotsakkeisiin, esimerkiksi:
- User-Agent: Mozilla/3.01Gold
(Win95; I)
- Accept-Language: en
- Palvelimen vastausotsakkeisiin, esimerkiksi:
- Server: Apache/1.3.20 (Unix)
PHP/4.0.6
- Location:
http://www.domain.invalid/uusi/
Tilakoodeista
Web-palvelimen lähettämällä
tilarivillä kerrotaan mm. onnistuiko pyyntö tai mahdollinen
syy epäonnistumiseen. Nämä tilatiedot annetaan
- palvelimen vastauskoodina ja
- "selväkielisinä" tekstinä
Vastauksen tilakoodit ovat jaettu
- informatiivisiin: 100-199
- onnistuneisiin pyyntöihin: 200-299
- uudelleen ohjattuihin: 300-399
- virheellisiin asiakkaan pyyntöihin: 400-499
- palvelimen virhekoodeihin (pyyntö oli kunnollinen,
mutta sitä ei pystytty käsittelemään): 500-599
Mainittakoon muutamia esimerkkejä:
- 100 Continue: Pyynnön alkuosa saatu.
Asiakas voi jatkaa pyyntöä.
- 200 OK: Asiakkaan pyyntö onnistui.
- 204 No Content: Vastauksessa ei ole
sisältöä eli dataosaa.
- 301 Moved Permanently: Pyydetty URL on
siirretty pysyvästi. Location-otsake kertoo uuden sijainnin.
- 400 Bad Request: Asiakkaan
pyynnössä syntaksivirhe.
- 403 Forbidden: Asiakkaalla ei ole
oikeuksia dokumenttiin. Palvelin ei halua tai voi kertoa syytä
tähän. Tyypillisesti esim. palvelimella olevien
Web-dokumenttien (mahdollisesti virheellisesti asetetut)
käyttöoikeudet estävät dokumentin palauttamista.
- 404 Not Found: Haluttua dokumenttia ei
löydy.
- 500 Internal Server Error: Palvelimen tai
suoritettavan ohjelman toiminnassa virhe.
|