WebApps

En aquesta pràctica ens iniciarem amb les tecnologies que s'utilitzen per al desenvolupament d'aplicacions web.

Necessitaràs tenir preparat un contenidor.

World Wide Web

El científic anglés Tim Berners-Lee va inventar la World Wide Web (WWW), Xarxa d'Abast Mundial, en 1989, mentre treballava al CERN.

Coneguda comunament com la Web, és un sistema d'informació on documents i altres recursos són identificats amb URLs (Uniform Resource Locators), com, per exemple, http://wikipedia.org, que poden ser enllaçats amb hypertext, i són accessibles a través d'Internet.
Els recrsos de la Web són transferits pels Servidors Web via l' Hypertext Transfer Protocol (HTTP) i es pot accedir a ells utilitzant el Navegador Web.

URL

Com hem dit, les URLs són identificadors de recursos. Els recursos poden ser molt diversos: pàgines, imatges, videos, fitxers, etcètera. Per exemple:

Una URL es compon de 7 components:

Anem a veure amb més detall aquests components.

Scheme

El protocol d'accés al recurs indica la forma concreta en que s'han de comunicar el que fa la petició i el que la respón.

Per exemple, el protocol http serveix per a comunicar amb un servidor web. La especificacio del protocol és molt extensa, però podem veure un exemple senzill.

En la seva forma més utilitzada, HTTP serveix per a obtenir recursos.

Suposem que volem obtenir la pàgina principal del CERN. Aleshores, hem de realitzar un petició HTTP al seu servidor (info.cern.ch). Les dades que enviarem al servidor han de seguir exactament el protocol.

Utilitzarem el programa nc per a comunicar amb el servidor del CERN.

Obre un terminal i executa la següent comanda:

@host nc info.cern.ch 80

Amb aquesta comanda hem connectat al port 80 del servidor del CERN.
Ara el servidor està esperant que li enviem dades.

Si enviem qualsevol dada al servidor, aquest no serà capaç de comprendre la petició. Li hem de enviar les dades adequades, seguint el protocol HTTP.

Prova a escriure alguna cosa, i polsa Intro per a enviar les dades al servidor.

El servidor respondrà amb un error 400 (Bad request). La petició no ha estat correcta.

Per a fer la petició correcta hem fer el següent:

  1. Connectem amb el servidor:

    nc info.cern.ch 80
  2. Escrivim la comanda GET,
    després el recurs que volem /index.html
    després la versió del protocol HTTP/1.0
    després un "retorn de carro" Ctrl + V Ctrl + M
    i per últim un "retorn de línia" Intro

    GET /index.html HTTP/1.0 Ctrl + V Ctrl + M Intro
  3. Especifiquem el Host al qual estem connectant
    introduint Host: info.cern.ch
    "retorn de carro" Ctrl + V Ctrl + M
    i "retorn de línia" Intro

    Host: info.cern.ch Ctrl + V Ctrl + M Intro
  4. Indiquem al servidor que ha finalitzat la petició amb
    "retorn de carro" Ctrl + V Ctrl + M
    i "retorn de línia" Intro

    Ctrl + V Ctrl + M Intro
  5. Aquest cop sí, el servidor ens respon amb 200 (OK), i ens retorna el recurs solicitat.

    Aquesta petició que hem realitzat a mà és exactament el que fa el navegador web quan introduim la URL http://info.cern.ch a la barra d'adreçes.

    Pots comprovar-ho de la següent forma:

    1. Obre una pestanya nova del Firefox

    2. Polsa F12 per a obrir les Eines de desenvolupador

    3. Ves a la pestanya

    4. Introdueix http://info.cern.ch/index.html a la barra d'adreçes i navega a la pàgina

    5. Firefox et mostrarà tots els recursos que està descarregant del servidor

    6. Selecciona el recurs index.html

    7. A la pestanya lateral , baixa fins a i activa l'opció

    Ahí pots veure tota la petició HTTP que s'ha realitzat:

    Ho farem ara al servidor que tenim instal·lat al nostre contenidor.

    User

    Alguns servidors requereixen d'autenticació amb usuari:contrasenya per a accedir a certs recursos

    Configurarem el nostre servidor per a requerir usuari:contrasenya en l'accés.

    Obrim el fitxer de configuració del servidor Apache:

    @container nano /etc/apache2/sites-enabled/000-default

    Afegim les següents línies per a activar l'accés amb usuari/password:

    /etc/apache2/sites-enabled/000-default <VirtualHost *:80> ServerAdmin webmaster@localhost DocumentRoot /var/www/html ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined <Directory /var/www/html> AllowOverride all </Directory> </VirtualHost>

    Creem l'usuari Juan:

    @container htpasswd -c /var/www/contrasenyes joan

    Comprovem que s'ha creat l'usuari:

    @container cat /var/www/contrasenyes

    Restringirem l'accés a la carepta /var/www/html a només aquells usuaris que estiguin en l'arxiu /var/www/contrasenyes. Per fer-ho hem de crear un fitxer anomenat .htaccess dintre de la carpeta que volem registringir:

    @container nano /var/www/html/.htaccess

    El contingut de l'arxiu .htaccess ha de ser aquest:

    /var/www/html/.htaccess AuthType Basic AuthName "Introdueix el teu usuari i contrasenya" AuthBasicProvider file AuthUserFile "/var/www/contrasenyes" Require valid-user

    Per últim reiniciem el servidor Apache:

    @container /etc/init.d/apache2 restart

    Host

    El host és l'adreça IP o nom DNS del servidor.

    Configurarem el servidor web per a que mostri dues pàgines diferents en funció del Host que se li indiqui en la petició:

    Crearem dues carpetes (aaa.com i bbb.com), i en cadascuna d'elles posarem una web diferent

    @container mkdir /var/www/html/aaa.com mkdir /var/www/html/bbb.com echo "<h1>welcome to aaa.com</h1>" > /var/www/html/aaa.com/index.html echo "<h1>welcome to bbb.com</h1>" > /var/www/html/bbb.com/index.html

    Canviem la configuració d'Apache per a que busqui els recursos que se li sol·licitin en una carpeta o l'altra en funció del Host (ServerName) que s'indiqui a la petició http:

    /etc/apache2/sites-enabled/000-default <VirtualHost *:80> ServerName aaa.com DocumentRoot /var/www/html/aaa.com </VirtualHost> <VirtualHost *:80> ServerName bbb.com DocumentRoot /var/www/html/bbb.com </VirtualHost>

    Realitzem dues peticions als diferents noms de host:

    @host printf 'GET /index.html HTTP/1.0\r\nHost aaa.com\r\n\r\n' | nc {IP_CONTENIDOR} 80 printf 'GET /index.html HTTP/1.0\r\nHost bbb.com\r\n\r\n' | nc {IP_CONTENIDOR} 80

    Observa que segons el Host indicat a la petició, es retorna una web o l'altra.

    Port

    Configurem Apache per a permetre conexions al port 8080:

    @host nano /etc/apache2/ports.conf /etc/apache2/ports.conf Listen 80 Listen 8080 # resta de lines # ...

    Servim dues pàgines diferents en funcio del port de conexió:

    /etc/apache2/sites-enabled/000-default <VirtualHost *:80> DocumentRoot /var/www/html/aaa.com </VirtualHost> <VirtualHost *:8080> DocumentRoot /var/www/html/bbb.com </VirtualHost>

    Accedim a http://ip_contenidor:80

    Accedim a http://ip_contenidor:8080

    Path

    Si no s'especifica cap arxiu en el path, per defecte, el servidor apache servirà l'arixu index.html, i si aquest arxiu no existeix, servirà una pàgina que llistarà els arxius del directori:

    Anem a crear diversos arxius al directory /var/www/html:

    @container echo "<h1>Home page</h1>" > /var/www/html/index.html echo "<h1>Pagina xxx </h1>" > /var/www/html/xxx.html echo "<h1>Pagina yyy </h1>" > /var/www/html/yyy.html echo "<h1>Pagina zzz </h1>" > /var/www/html/zzz.html

    Comprovem que tenim aquests arxius a /var/www/html:

    @container ls /var/www/html index.html xxx.html yyy.html zzz.html

    Si ara fem una petició al servidor sense indicar cap arxiu http://10.2.4.1 el servidor ens enviarà l'arxiu index.html

    Si especifiquem algun arxiu a la petició (e.g. http://10.2.4.1/xxx.html) Apache ens servirà aquest arxiu.

    Si l'arxiu que posem a la url (e.g. http://10.2.4.1/opq.html) no existeix, apache ens servirà una pàgina "Not Found"

    Per últim, esborrem l'arxiu index.html:

    @container rm /var/www/html/index.html

    ... i comprovem que Apache ens mostra un pàgina amb la llista d'arxius del directori, quan no especifiquem cap arxiu a la url http://10.2.4.1/ i no hi ha un index.html:

    Al path de la url també es poden especificar els directoris on es troba l'arxiu que se solicita. Apache buscarà aquest arxius a partir del DocumentRoot.

    Per exemple, si el DocumentRoot és /var/www/html, i fem aquesta petició: http://10.2.4.1/aaa/bbb/mmm.html, Apache buscarà aquest arxiu /var/www/html/aaa/bbb/mmm.html. Comprovem-ho:

    @container mkdir -p /var/www/html/aaa/bbb/ echo "<h1>Pagina mmm </h1>" > /var/www/html/aaa/bbb/mmm.html

    Comprova que s'accedeix al recurs mmm.html amb aquesta URL http://10.2.4.1/aaa/bbb/mmm.html.

    Ara anem a canviar el DocumentRoot, i farem que sigui /var/www/html/aaa/:

    /etc/apache2/sites-enabled/000-default <VirtualHost *:80> DocumentRoot /var/www/html/aaa </VirtualHost>

    Reiniciem el servidor:

    @container /etc/init.d/apache2 restart

    Ara, per a accedir al recurs mmm.html, la URL que cal posar és http://10.2.4.1/bbb/mmm.html.

    Query

    La query serveix per a passar dades extra al recurs que s'està solicitant.

    Veiem un exmple:

    En aquesta url https://www.google.com/search?q=animals, estem passant al recurs search la dada extra q=animals. Aquest recurs ja sabrà que fer amb aquesta dada extra. Si li passem una query que el recurs no sap processar, normalment la ignorarà: https://www.google.com/search?jajaja=jejeje.

    Anem a fer al nostre contenidor un recurs que accepti una query amb dades extra i faci alguna cosa amb aquestes dades.

    Abans anem a ressetejar la configuració d'Apache, ja que abans l'hem deixat una mica trastocada. Tornarem a posar el DocumentRoot al seu lloc habitual.

    @container printf "<VirtualHost *:80>\n\tDocumentRoot /var/www/html\n</VirtualHost>" > /etc/apache2/sites-enabled/000-default.conf /etc/init.d/apache2 restart

    Primer hem de comprendre que el recurs no pot ser una pàgina HTML, ja que el llenguatge HTML només és per a definir el contingut de la pàgina. És a dir, amb HTML no podem accedir a les dades de la query.

    Un llenguatge que sí pot obtenir les dades de la query i fer alguna cosa amb aquestes dades es PHP. Anem a veure uns exemples simples amb el que es pot fer amb PHP.

    Primer l'instal·lem:

    @container apt install -y php

    Crearem un senzill script php que ens permetrà executar comandes al servidor a través del navegador web.

    Anomenarem aquest recurs WEBASH (web + bash):

    @container nano /var/www/html/webash.php

    Afegim el següent codi a l'arxiu webash.php:

    /var/www/html/webash.php <?php echo "<style> body { font-family: Consolas, monospace; }</style>"; echo "<span style='font-size: 2em;'>webash/</span>"; echo "<span>web&bash</span>"; ?>

    Si accedim al recurs http://10.2.4.164/webash.php veurem la pàgina generada per l'script webash.php:

    Fixa't que el que fa l'script php és generar codi HTML amb els echo. Apache executa l'script i retorna al navegador tot el que ha mostrar l'script amb els echo.

    Per a generar codi html posarem echo, el codi html entre cometes "" i punt-i-coma ;:

    echo "codi html";

    Tot el codi PHP que escrivim ha d'anar dintre de les etiquetes <?php i ?>:

    <?php // codi PHP ?>

    De moment, el nostre codi PHP sempre mostra el mateix contingut, independentment de la query que li passem. És a dir, posis les dades que posis a la query, l'script les ignorarà. Per exemple: http://10.2.4.164/webash.php?comanda=pstree, o http://10.2.4.164/webash.php?hola=quetal

    Anem a modificar l'script per que agafi una dada de la query i faci alguna cosa:

    Afegim aquestes línies de codi a l'arxiu webash.php:

    /var/www/html/webash.php <?php echo "<style> body { font-family: Consolas, monospace; }</style>"; echo "<span style='font-size: 2em;'>webash/</span>"; echo "<span>web&bash</span>"; echo "<h1>Hola "; echo $_GET['usuari']; echo "</h1>"; ?>

    Ara posem la query usuari=gerard a la url: http://10.2.4.164/webash.php?usuari=gerard. L'script php genera aquesta web:

    Amb el codi $_GET['usuari'] de la línia 7, hem obtingut el valor de la dada usuari de la query, i l'hem utilitzat per a generar el contingut de l'etiqueta <h1>.

    Si fas la query amb un altre valor per a la dada usuari, l'script generarà un altre codi html que inclourà aquest valor.

    Per contra, si canvies la paraula usuari per una altra cosa, l'script ignorarà la dada.

    Quan introduïm alguna cosa en el camp de text, per exemple hola i li donem al botó Executar

    Avançarem amb el webash, i ara farem que se li passi una dada anomenada comanda. L'script agafarà el valor d'aquesta dada i l'executarà al sistema operatiu.

    Esborra les línies anteriors, i afegeix aquesta línia:

    /var/www/html/webash.php <?php echo "<style> body { font-family: Consolas, monospace; }</style>"; echo "<span style='font-size: 2em;'>webash/</span>"; echo "<span>web&bash</span>"; system($_GET['comanda']); ?>

    Ara l'script agafarà el valor de la dada anomenada comanda i l'executarà. Per exemple podem executar la pstree així: http://10.2.4.164/webash.php?comanda=pstree:

    La funció system executa el que se li posi entre els parèntesi, i el resultat de la comanda, s'inclou a la pàgina generada.

    El que està executant aleshores la funció system és el valor de la dada comanda de la query. Prova a posar aquesta url http://10.2.4.164/webash.php?comanda=cal o qualsevol altra comanda a la query.

    Seguirem ara donant un mica d'estil a les dades generades per system, ja que queden totes seguides i sense format. Posarem tot el que genera el system dintre d'un element <pre>. Li posarem també una mica d'estil CSS al <pre>.

    /var/www/html/webash.php <?php echo "<style> body { font-family: Consolas, monospace; }</style>"; echo "<span style='font-size: 2em;'>webash/</span>"; echo "<span>web&bash</span>"; echo "<pre style='width: 80ch; padding: 2ch; overflow: auto; color: white; background: #300A24;'>"; system($_GET['comanda']); echo "</pre>"; ?>

    Provem a veure com queda http://10.2.4.164/webash.php?comanda=df -h

    Per últim, afegirem a webash una forma més còmoda de realitzar comandes, que no sigui posant-les a la url. Afegirem un formulari amb un camp de text i un botó:

    /var/www/html/webash.php <?php echo "<style> body { font-family: Consolas, monospace; }</style>"; echo "<span style='font-size: 2em;'>webash/</span>"; echo "<span>web&bash</span>"; echo "<form>"; echo "<input name='comanda'>"; echo "<input type='submit' value='Executar'>"; echo "</form>"; echo "<pre style='width: 80ch; padding: 2ch; overflow: auto; color: white; background: #300A24;'>"; system($_GET['comanda']); echo "</pre>"; ?>

    Ara ens serà més còmode executar una comanda:

    Quan es premi el botó Executar, automàticament el navegador web agafarà els camps del <form> i els afegirà a la query de la petició. Anomenarà les dades de la query segons l'atribut name dels <input> i el valor serà el que s'hagi escrit en ells. Prova a executar algunes comandes!

    Acabarem fent un algunes de consideracions.

    La primera és que si tractes de fer una comanda invàlida, no veuràs cap error, ja que la funció system, només mostra les dades de la sortida estàndard (STDOUT). Si volem veure també les dades que es mostren a la sortida d'errors (STDERR), podem redirigir-ho amb exec 2>&1. Canvia la línia indicada:

    /var/www/html/webash.php <?php echo "<style> body { font-family: Consolas, monospace; }</style>"; echo "<span style='font-size: 2em;'>webash/</span>"; echo "<span>web&bash</span>"; echo "<form>"; echo "<input name='comanda'>"; echo "<input type='submit' value='Executar'>"; echo "</form>"; echo "<pre style='width: 80ch; padding: 2ch; overflow: auto; color: white; background: #300A24;'>"; system("exec 2>&1 && " . $_GET['comanda']); echo "</pre>"; ?>

    Ara prova a executar qualsevol comanda que generi errors i sí es mostraran:

    La segona consideració és que les comandes s'executen amb els permisos de l'usuari www-data, i això significa que només podran fer allò que l'usuari www-data tingui permès fer. Per exemple:

    L'ultima consideració és que el directori de treball és on es troba l'arxiu webash.php, així que totes les rutes que hi hagi a les comandes són relatives a aquest directori:

    Fragment

    El fragment serveix per a fer que el navegador posicioni la pàgina en una secció determinada. Aquesta part de la url no arriba al servidor, és el navegador el qui ha de saber com gestionar el fragment.

    Veiem un exmple:

    Generem un arxiu html extens amb 5 seccions (id=sX) i 30 paràrafs en cada secció:

    @container for i in {1..5}; do printf "<h1 id='s$i'>Seccio $i</h1>; for j in {1..30}; do printf "<p>seccio $i, paràgraf $j</p>"; done; done > /var/www/html/llarg.html

    Prova a navegar directament a alguna de les seccions del document.

    Per a definir una secció en un document hem d'afegir l'atribut id a l'element que desitjem. Per a navegar directament a una secció, només cal afegir un # seguit del valor del seu atribut id.

Servidor web

El servidor web és un software que respon a les peticions dels clients en la WWW. Un servidor web pot tenir un o més llocs web.

Hi ha una àmplia varitat de software que s'utilitza com a servidor web. Els que més quota de mercat tenen actualment són: Apache (44.3%) i nginx (41%).

Servir recursos

La tasca principal d'un servidor web és respondre a les peticions HTTP amb els recursos solicitats.

Els recursos que entrega el servidor web als clients són freqüentment fitxers amb codi HTML, codi CSS i codi Javascript. També pot enviar altres tipos de recursos com imatges, videos i arxius de tot tipus.

Veiem un exemple. Descarrega aquest vídeo de Tim Berners-Lee al directory /var/www/html del servidor:

@container wget -O /var/www/html/tim.webm https://upload.wikimedia.org/wikipedia/commons/7/7b/What_is_the_future_of_the_internet-_-_Tim_Berners_Lee.webm

Utilitza el client Firefox per a fer una petició d'aquest recurs al servidor: http://10.2.4.100/tim.webm.

Estàtic vs Dinàmic

Un servidor web pot servir contingut estàtic o dinàmic:

Veiem un exemple: Serverdate

Crea aquest arxiu al servidor:

/var/www/html/serverdate.html <!DOCTYPE html> <p>La data del servidor es: Tue Oct 20 10:13:08 UTC 2020</p>

Navega a http://10.2.1.24/serverdate.html

El recurs serverdate.html és un recurs estàtic. El servidor web el servirà tal qual, per això encara que recarregis la pàgina, la data/hora no canviarà.

Provem a fer un continugt dinàmic:

Instal·la php al servidor:

@container apt install -y php

Escriu aquest script PHP:

/var/www/html/serverdate.php <?php echo "<p>La data del servidor es: "; system(date); echo "</p>"; ?>

Ara, cada vegada que navegues al recurs http://10.1.2.23/serverdate.php el servidor web executa l'script i envia al client el recurs resultant. La comanda system(date) obté l'hora actual del servidor, per tant cada vegada que recarreguis la pàgina, obtindràs l'hora actual.

Base de dades

La majoria d'aplicacions web utilitzen una base de dades per a emmagatzemar la informació que han de mostrar. Els scripts poden guardar i obtenir la informació d'elles (com per exemple, les publicacions que fan els usuaris a una xarxa social).

Farem una aplicació web anomenada TheWall on els visitants podran escriure una firma, i totes les firmes que es vagin posant es mostraran a la pàgina.

Instal·la el gestor de bases de dades MySQL:

@container apt install -y mysql-server

Crearem una base de dades per a la app TheWall:

@container mysql -e "CREATE DATABASE thewalldb"

Ara crearem un usuari per a administrar aquesta base de dades:

@container mysql -e "CREATE USER 'thewalldbadmin'@'localhost' IDENTIFIED BY 'pass123'"

Li donem privilegis a l'usuari thewalldbadmin per a administrar la base de dades thewalldb:

@container mysql -e "GRANT ALL PRIVILEGES ON thewalldb.* TO 'thewalldbadmin'@'localhost'; FLUSH PRIVILEGES"

El més habitual és que les bases de dades emmagatzemin la informació en taules. Per a la nostra app crearem una taula firmes on es s'aniran guardant les firmes dels visitants. Aquesta taula només tindrà un camp que contindrà una firma.

@container mysql -e "CREATE TABLE thewalldb.firmes(firma TEXT)"

Insertarem unes quantes firmes de mostra a la taula firmes:

@container mysql -e "INSERT INTO thewalldb.firmes VALUES('hola que tal')" mysql -e "INSERT INTO thewalldb.firmes VALUES('pasaba por aqui')" mysql -e "INSERT INTO thewalldb.firmes VALUES('jajajaaajaaa')" mysql -e "INSERT INTO thewalldb.firmes VALUES('que hay que poner aqui?')"

Podem veure que les firmes s'han introduït a la taula firmes així:

@container mysql -e "SELECT * FROM thewalldb.firmes"

Ara el següent pas es programar un script PHP que obtingui la informació de la base de dades i la posi en la pàgina web que generi.

Insal·larem el paquet php-mysql que permet connectar a una base de dades MySQL des d'un script PHP:

@container apt install -y php-mysql

L'script que connecta a la base de dades thewalldb, obté totes les firmes i les volca a la pàgina és aquest:

/var/www/html/thewall.php <?php $db = new mysqli("localhost", "thewalldbadmin", "pass123", "thewalldb"); foreach ($db->query("SELECT * FROM firmes") as $fila) { echo $fila['firma']; } ?>

Naveguem a http://10.1.2.4/thewall.php i veurem com l'script a volcat totes les firmes de la base de dades:

Aquest contingut és dinàmic: depèn del contingut de la base de dades. Ho podem comprovar afegint més firmes a la base de dades:

@container mysql -e "INSERT INTO thewalldb.firmes VALUES('te quiero')" mysql -e "INSERT INTO thewalldb.firmes VALUES('que pasa?')" mysql -e "INSERT INTO thewalldb.firmes VALUES('nunca te olvidare')"

Acabarem la app thewall permetent que els visitants escriguin la seva firma. Aquesta firma s'enviarà a l'script en la query, i l'script l'obtindrà i la guardarà a la base de dades.

/var/www/html/thewall.php <form> <input name="firma"> <input type="submit" value="Firmar"> </form> <?php $db = new mysqli("localhost", "thewalldbadmin", "pass123", "thewalldb"); if (isset($_GET["firma"])) { $stmt = $db->prepare("INSERT INTO firmes VALUES(?)"); $stmt->bind_param("s", $_GET["firma"]); $stmt->execute(); $stmt->close(); } foreach ($db->query("SELECT * FROM firmes") as $fila) { echo $fila['firma']; } ?>

Client web

Un client web és un software per a realitzar peticions HTTP a un servidor web.

Els navegadors web són clients web que connecten a un servidor, descarreguen les seves pàgines i les mostren a l'usuari.

També hi ha altres clients web que només descarreguen les pàgines d'un servidor, sense mostrar-les. Un exemple d'aquests clients són wget i curl. Són dos programes de consola capaços de descarregar una pàgina web o un altre recurs. Veiem un exemple d'ús wget:

@host wget info.cern.ch

Amb aquesta comanda, wget ha realitzat la petició al servidor info.cern.ch i ha guardat la pàgina. Podem veure el contingut de la pàgina amb aquesta comanda:

@host cat index.html

El que veiem és el codi HTML de la pàgina index.html.

Els navegadors web, a més de descarregar la pàgina, interpreten el codi HTML i el mostren a l'usuari, permetent-li navegar dintre d'ella o fer click als seus enllaços per a navegar a altres pàgines.

Hi ha navegadors web que s'executen en mode gràfic (Firefox, Chrome, etc.) i altres que es poden executar a la consola en mode text. Alguns exemples són: lynx, w3m, browsh. Provem el lynx:

@container apt install lynx @container lynx info.cern.ch

Pàgines web

Les pàgines web són una colecció d'informació que consisteix en un o més fitxers de text escrits en HTML. Les pàgines web també poden fer ús de codi JavaScript, i codi CSS:

Veiem un petit exemple:

index.html <p>HTML & CSS & JavaScript</p> <style> @import url('https://fonts.googleapis.com/css2?family=Gloria+Hallelujah'); p { font-family: 'Gloria Hallelujah'; font-size: 48px; color: #f7d21f; font-weight: bold; } </style> <script> setInterval(() => { document.body.insertAdjacentHTML('beforeend', '<img src="https://raw.githubusercontent.com/smxm8/static/main/homer.png"'); }, 1000); </script>