CGI-ohjelmointi, HTTP-protokolla

Jatketaan Pythonin, CGI-ohjelmoinnin ja HTTP-protokollan parissa.

Uusin Python ja CGI-ohjelmointiluento (youtube)

Vanha Python ja CGI-ohjelmointiluento (youtube)

Luentoesimerkit: jinja.cgi-esimerkki (Lähdekoodi, Jinja template)

Toinen jinja-esimerkki (Lähdekoodi, Pohjatemplate, Toinen template)

JSON, omat luokat, lomakkeen korvaaminen linkillä (Lähdekoodi, Template )

ostoskori.cgi (lähdekoodi, template)

Lomake - form

form-elementti määrittelee lomakkeen varsinaisen alkamis- ja loppumiskohdan. form-elementin sisään sijoitetaan kaikki varsinaiset lomake-elementit (tekstikentät, valintaruudut, yms.), jotka tulevat näkyviin lomakkeelle. form-elementin attribuuteilla eli ominaisuuksilla voidaan määritellä tarkemmin lomakkeen käyttäytymistä. Seuraavassa lyhyt esimerkki form-elementin käytöstä:

<!DOCTYPE html>
<html>
<head>
<title>Esimerkkilomake</title>
</head>
<body>
<h1>Esimerkkilomake</h1>
<form action="http://palvelin/teepase.cgi" method="post">
.. lomake-elementit tulevat tänne..
</form>
</body>
</html>

action-attribuutti

action-attribuutti kertoo lomakkeelle osoitteen, jossa lomakkeen käsittelevä CGI-ohjelma sijaitsee. Seuraavassa muutama esimerkki action-attribuutin käytöstä. Ensimmäisessä esimerkissä on perinteinen absoluuttinen hakemistoviittaus ohjelmaan, joka käsittelee lomakkeelle syötetyn datan.

<form action="http://palvelin/teepase.cgi" method="post">

Edellisen esimerkin mukaisesti lähetettynä data tulee koodattuna application/x-www-form-urlencoded-muodossa.

<form action="http://palvelin/teepase.cgi" method="post" enctype="multipart/form-data">

Antamalla enctype-attribuutin arvoksi multipart/form-data voidaan lomakkeeseen lisätä myös tiedostoja

method-attribuutti

method-attribuutti kertoo kuinka lomakkeen sisältämä data toimitetaan datan käsittelevälle ohjelmalle. Attribuutin mahdolliset arvot ovat post ja get.

method-attribuutti arvolla get saa aikaan lomakkeella olevien tietojen siirtämisen URL:n yhteydessä. Seuraavassa on esitelty muoto, jossa tiedot siirretään lomakkeen käsittelevälle ohjelmalle. Lomakkeelta siirrettävät tiedot ovat nähtävillä selaimen osoitepalkissa (location, address)

http://palvelin/teepase.cgi?Nimi=Etunimi+Sukunimi&email=Sahk%F6postiosoite&kommentti=t%E4h%E4n+kommentti&laheta=L%E4het%E4+kommenttisi

URL:n mukana tulevien tietojen muoto näyttää ensi silmäyksellä sekavalle. Kuitenkin sieltä on helposti erotettavissa lomakkeen tiedot. Lomakkeen käsittelevän ohjelman osoite ja lomakkeen tiedot on erotettu kysymysmerkillä (?). Eri kenttien tiedot on erotettu &-merkillä. Lomakekentän nimi ja arvo on erotettu yhtä suuri kuin -merkillä (=). Lomakkeessa olevat skandit (ä,ö,å) ja erikoismerkit on koodattu heksadesimaaliluvuiksi ja välilyöntien paikalla on plus-merkki (+) tai %20.

Graphic1

GET-metodin käyttäminen soveltuu ainoastaan hyvin pienille lomakkeille, koska kaikki sen sisältämät tiedot siirretään URL:n mukana. GET-metodia käytetään silloin kun halutaan etsiä jotain tietoa eikä tehdä mitään muutoksia.

POST-metodia käytettäessä tiedot eivät siirry URL:n mukana, vaan vastaanottavan ohjelman on luettava ne STDIN-muuttujasta. POST-arvoa kannattaa käyttää erityisesti suuren tietomäärän siirtämiseksi lomakkeelta käsittelevälle ohjelmalle. Lomakkeelta siirtyvät tiedot eivät myöskään ole käyttäjän nähtävissä käytettäessä post-metodia. POST-metodia käytetään kun lomake aiheuttaa lisäyksiä, muutoksia tai poistoja

<!DOCTYPE html">
<html>
<head>
<title>Esimerkkilomake</title>
</head>
<body>
<h1>Esimerkkilomake</h1>
<form action="http://palvelin/teepase.cgi" method="post">
<p>
<label for="name">Nimi: </label>
<input id="name" type="text" name="Nimi" value="Etunimi Sukunimi" />
</p>
<p>
<label for="email">Email: </label>
<input id="email" type="text" name="email" value="Sahköpostiosoite" />
</p>
<p>
<label for="kommentti">Kommentti: </label>
<input id="kommentti" type="text" name="kommentti" value="tähän kommentti" />
</p>
<p>
<input type="submit" name="laheta" value="Lähetä kommenttisi" />
</p>
</form>
</body>
</html>

Lomake-elementit käsitellään tarkemmin ITKP1011-kurssilla.

Lomakkeen käsittely

Lomakkeen käsittely

  1. Selainohjelma pyytää palvelimelta lomakesivun HTTP-protokollan mukaisilla otsikkotiedoilla.
  2. Palvelin vastaa selaimelle HTTP-protokollan mukaisilla otsikkotiedoilla, jonka jälkeen tarjoaa WWW-sivun datan eli HTML-koodia.
  3. Käyttäjä täyttää ja hyväksyy lomakkeen. Selain lähettää lomakkeen tiedot WWW-palvelimella suoritettavalle ohjelmalle.
  4. Lomakkeella oleva data käsitellään ohjelman tekijän haluamalla tavalla.
  5. Ohjelma palauttaa käyttäjälle virheilmoituksen tai ilmoituksen onnistumisesta, esim. lomakkeen korjauspyynnöillä tai tulossivun.

Lomakkeen käsittely

HTTP (HyperText Transfer Protocol)

HTTP on protokolla, jonka avulla selain ja WWW-palvelin keskustelevat.

Firefox-selaimen ja WWW-palvelimen välistä HTTP-liikennettä on helppo seurata Firebugilla tai Tamper Data -laajennuksella .

Selain lähettää WWW-palvelimelle pyynnön:

GET /sovellukset/testi.html HTTP/1.1
Connection: keep-alive
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,video/x-mng,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Accept-Encoding: gzip,deflate
Accept-Language: en-us,en;q=0.5
Host: appro.mit.jyu.fi
Referer: http://appro.mit.jyu.fi/
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.4) Gecko/20030624
Keep-Alive: 300
Selaimen lähettämät HTTP-otsakkeet selityksineen
GET /sovellukset/testi.html HTTP/1.0 Pyydetään informaatiota (GET), jonka osoite palvelimella on /sovellukset/testi.html käyttäen HTTP/1.1-protokollaa.
Connection: keep-alive Käsketään pitää yhteys päällä.
Accept: text/xml, application/xml, application/xhtml+xml, text/html;q=0.9, text/plain;q=0.8, video/x-mng, image/png, image/jpeg, image/gif;q=0.2, */*;q=0.1 Luetellaan selaimen ymmärtämät mediatyypit. Kerrotaan myös mitä mediatyyppejä suositaan q-arvojen avulla.
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Luetellaan kelpaavat merkistöt.
Accept-Encoding: gzip,deflate Luetellaan tuetut koodaustavat (pakkaus).
Accept-Language: en-us,en;q=0.5 Halutut kielet
Host: appro.mit.jyu.fi Palvelimen nimi
Referer: http://appro.mit.jyu.fi/ Osoite, josta ollaan tulossa (sivu, jolla olevaa linkkiä on klikattu).
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.4) Gecko/20030624 Selaimen tiedot
Keep-Alive: 300Kertoo kuinka monta sekuntia yhteyttä pidetään yllä. Vain HTTP/1.0-protokollassa, mutta käytetään yhteensopivuussyistä. Oikeastaan muoto pitäisi olla Keep-Alive: parametri=arvo.

Palvelin vastaa:

HTTP/1.1 200 OK
Connection: close
Date: Tue, 06 Apr 2004 10:53:18 GMT
Accept-Ranges: bytes
ETag: "2da29-2147-4044819d"
Server: Apache/1.3.27 (Unix)  (Red-Hat/Linux) PHP/4.1.2 mod_perl/1.26
Vary: Accept
Content-Length: 414
Content-Type: application/xhtml+xml; charset=iso-8859-1
Last-Modified: Tue, 02 Mar 2004 12:44:13 GMT

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fi" >
<head>
  <title>Testisivu</title>
  <link href="testi.css" rel="StyleSheet" type="text/css" />
</head>
<body>
  <h1>Testiotsikko</h1>
  <p>Testitekstiä</p>
</body>
</html>
WWW-palvelimen vastaus
HTTP/1.1 200 OKStatuskoodi - kaikki kunnossa.
Connection: close Palvelin sulkee yhteyden. Normaalisti yhteys on pysyvä (persistent), jotta selain voi tehdä useita pyyntöä (kuvat, css, javascript jne.).
Date: Tue, 06 Apr 2004 10:53:18 GMT Päivä ja aika, koska vastaus on lähetetty.
Accept-Ranges: bytes Sallitaan tavuina määritellyt pyynnöt joissa halutaan vain osa dokumentista.
ETag: "2da29-2147-4044819d" Tunniste. Tunniste muuttuu dokumenttia muutettaessa.
Server: Apache/1.3.27 (Unix) (Red-Hat/Linux) AxKit/1.62 mod_python/2.7.8 Python/1.5.2 mod_ssl/2.8.12 OpenSSL/0.9.6b DAV/1.0.3 PHP/4.1.2 mod_perl/1.26 mod_throttle/3.1.2WWW-palvelimen tiedot
Vary: Accept-Encoding Vaihteleeko pyydetty resurssi jonkun ehdon mukaan. Tärkeä tieto esim. välimuisteille. Accept-Encoding: esim. erilainen pakkaus. Accept-Language: tarjolla useita kieliversioita. User-Agent: sivun sisältö riippuu selaimesta.
Content-Length: 414 Sisällön koko
Content-Type: application/xhtml+xml; charset=iso-8859-1Mediatyyppi ja merkistö
Last-Modified: Tue, 02 Mar 2004 12:44:13 GMTMilloin viimeksi muutettu.

HTTP-otsikoita voi tutkia tarkemmin esim. seuraavilla ohjelmilla:

HTTP Status Codes

Palvelin palauttaa vastauksessa HTTP-statuskoodin, joka kertoo lyhyesti selaimelle miten pyyntö onnistui ja miten tulee jatkossa toimia. Listassa yleisimmät:

Lisätietoa

Pythonin cgi-kirjasto

lomake.cgi (lomake.txt)

HTML:n erikoismerkit (<, > ja &) pitää muistaa koodata entiteeteiksi. Apuna voi käyttää cgi.escape-metodia. Attribuuttien arvot voi koodata xml.sax.saxutils.quoteattr-metodilla.

URLien kielletyt merkit voi koodata urllib.quote-metodilla.

Templatet ja Jinja

Yhtenäisen sivuston eri sivuilla on usein samankaltaisia osia, jotka joudutaan jokaisella sivulla liittämään includella tai copy&pastella jokaiselle sivulle. Näitä osia ovat esimerkiksi navigoinnit ja autentikoinnista huolehtiminen. Entäpä jos joltain sivulta tärkeitä kuten käyttäjätarkistus unohtuukin?

Templateilla (eli sivupohjilla) saavutetaan seuraavia etuja:

Sivun sisältämää html-koodia ei pidä kirjoittaa suoraan python-ohjelman sisään, koska silloin tuloksena on ylläpitokelvoton koodin ja html:n sekasotku. Pyritään MVC-malliin jossa ohjelman toimintalogiikka (controller) pidetään erossa näkymästä (view) eli www-sivun sisällöstä. Tämä onnistuu helposti käyttämällä templateja. Yksi käytetyimpiä on Jinja2.

Jinja2 documentation

Jinjan koodi erotetaan html-koodista jollakin seuraavista:

Muuttujien arvoja voi muokata Jinjan filttereillä. Filtteri ja muuttuja erotetaan toisistaan |-merkillä. Esim. lista|len palauttaa listan pituuden. Jos automatic escaping ei ole päällä niin jää omalle vastuulle varmistaa, että kaikkien muuttujien sisältö kelpaa html:ään. Tämä voidaan varmistaa e-filtterillä: muuttuja|e

Jinjan for-loopissa voi käyttää apuna loop-muuttujan arvoja. Esim. loop.index antaa 1-alkuisen kierroksen indeksin ja loop.index0 0-alkuisen. Jinja silmukkaa ei voi breakata.

Jos tarvii Jinjassa luoda uusia muuttujia niin se on tehtävä set-komennolla:

{% set muuttuja = arvo %}

Katso jinja.cgi-esimerkki (Lähdekoodi, Jinja template)

Toinen jinja-esimerkki (Lähdekoodi, Pohjatemplate, Toinen template)

Python, merkistöt ja erikoismerkit webissä

Decode In Encode Out

Peruskaava on Decode in Encode out

Käyttäjien kommentit

Kommentoi Lisää kommentti
Kurssimateriaalien käyttäminen kaupallisiin tarkoituksiin tai opetusmateriaalina ilman lupaa on ehdottomasti kielletty!
https://appro.mit.jyu.fi/tiea2080/luennot/cgi/
© Tommi Lahtonen (tommi.j.lahtonen@jyu.fi) <https://hazor.iki.fi/>
2021-03-09 09:49:30
Informaatioteknologia - Jyväskylän yliopiston informaatioteknologian tiedekunta