--- title: Apache2. Servidors d'aplicacions web tags: daw, M8 --- <div style="width: 45%; margin-left: auto;"> ![](https://hackmd.io/_uploads/HJiR4eGJT.png) ![image](https://hackmd.io/_uploads/By3ai4Bolx.png) </div> <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"><img alt="Llicència de Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" /></a><br />Aquesta obra està subjecta a una llicència de <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">Reconeixement-CompartirIgual 4.0 Internacional de Creative Commons</a> # Servidors d'aplicacions web * [vincle a font en MarkDown](https://hackmd.io/@JdaXaviQ/S1MNdT4x9) --- ## 1. Common Gateway Interface (CGI). CGI és el mecanisme més primitiu per a enviar contingut web dinàmic a través d'un servidor web. Utilitza variables d'entorn i els fluxos estàndar (stdin/stdout) per a comunicar amb el programa executat. A més, si estem cridant a un llenguatge interpretat com per exemple Python, necessita cridar a l'intèrpret quan es realitza la crida des del client. Si esteu acostumats a servir aplicacions PHP en altres moduls, aquesta forma us semblarà molt natural, però no vol dir que sigui la millor. Per a poder executar programes per CGI necessiteu habilitar el mòdul mod_cgi: ```sudo a2enmod cgi``` ### Exemple de crida a un programa Python amb CGI clàssic. El programa: ```python= #!/usr/bin/python3 # -*- encodign: utf-8 -*- def send_html_content(): print("Content-type: text/html\n\n") print("<!DOCTYPE html>") print("<html><head><title>Hola DAW</title></head>") print("<body><h1>Hola DAW</h1></body></html>") send_html_content() ``` Assegurar-s'hi de que té permisos d'execució '755'. ```bash= -rwxr-xr-x 1 xavi xavi 269 feb 31 25:62 test.py ``` Habilitar l'execució d'scripts CGI al directori on hem desat el nostre programa: ``` <Directory /var/www/cgi-bin/> Options +ExecCGI AddHandler cgi-script .cgi .pl .py AllowOverride All Require all granted </Directory> ``` I eventualment activar un nou servidor virtual si aquest directori queda fora dels directoris servits pels servidors actius. ## 2. Web Server Gateway Interface (WSGI). WSGI és una interface desenvolupada per la comunitat Python que permet que els navegador puguin carregar l'intèrpret de Python de manera prèvia a l'arrivada de les peticions i que cada petició web es transformi en una crida a una funció que rep la informació d'entorn i una callback com a paràmetres, amb el consegüent estalvi de temps i de recursos. ### Exemple d'aplicació servida des de WSGI. Primer de tot necessitem un mòdul de WSGI al nostre apache: ```bash= sudo apt install libapache2-mod-wsgi-py3 ``` La mínima expressió d'una aplicació WSGI consistiria només en una funció que per defecte s'ha d'anomenar 'application' i ha de poder rebre dos paràmetres (environ, start_response). ```python= #!/usr/bin/python3 # -*- encodign: utf-8 -*- def application(environ, start_response): status = '200 OK' output = b'Hello World!' response_headers = [('Content-type', 'text/plain'), ('Content-Length', str(len(output)))] start_response(status, response_headers) return [output] ``` I afegim la informació de la nostra aplicació al servidor web: ``` WSGIScriptAlias /myapp /var/www/cgi-bin/la_meva_wsgi.wsgi ``` Ara ja podem cridar a la nostra aplicació: ``` $curl -X GET http://cgi.localhost/myapp Hello World! ``` ### Delegant la execució a processos '_Daemon_': Si volem evitar haver de reiniciar el nostre Apache desprès de fer canvis al codi python o volem tenir un control del nombre de processos llestos per a servir la nostra aplicació, en els sistemes Unix, podem delegar l'execució de l'intèrpret de Python a un grup de processos diferents del procés arrel d'Apache. ``` WSGIDaemonProcess cgi.localhost processes=2 threads=15 display-name=%{GROUP} WSGIProcessGroup cgi.localhost ``` Així ha quedat la configuració del meu servidor virtual: ``` <VirtualHost *:80> ServerName cgi.localhost ServerAdmin webmaster@localhost DocumentRoot /var/www/cgi-bin ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined WSGIDaemonProcess cgi.localhost processes=2 threads=15 display-name=%{GROUP} WSGIProcessGroup cgi.localhost WSGIScriptAlias /myapp /var/www/cgi-bin/la_meva_wsgi.wsgi </VirtualHost> ``` ## 3. Asynchronous Server Gateway Interface (ASGI). ASGI és el succesor natural de WSGI, al igual que WSGI defineix una interface entre el servidor web i la nostra aplicació Python, però aquesta vegada ho fa de forma asícrona, obrint la porta a eines que la web ha anat incorporant els darrers anys com poden ser els web-sockets i els sse (server sent events). En aquest cas l'aplicació rep 3 paràmetres en lloc de 2. ```python= async def application(scope, receive, send): event = await receive() ... await send({"type": "websocket.send", ...}) ``` On receive és una callback per a rebre comunicacions i send és una altra callback per a enviar informació al client. ASGI ha estat dissenyada per a oferir compatibilitat a aplicacions WSGI mitjançant alguna eina de traducció. [Documentació acerca d'ASGI](https://asgi.readthedocs.io/en/latest/introduction.html)