Professional Documents
Culture Documents
Mikoaj Olszewski
Wicej ycia
Serwer HTTP tworzony na zajciach Serwowanie statycznej treci (zawarto pliku lub katalogu) Jak serwowa tre dynamiczn? podmiana statycznej treci przez zewntrzny proces uruchomienie zewntrznego procesu / skryptu
Zewntrzny skrypt
In [1]: def run_python_script(URI): script = os.path.join(root_dir, URI) result = subprocess.check_output(["python", script]) return result
rodowisko
$ printenv VARIABLE=pewna wartosc LC_PAPER=pl_PL.UTF-8 LC_ADDRESS=pl_PL.UTF-8 SSH_AGENT_PID=3224 LC_MONETARY=pl_PL.UTF-8 GPG_AGENT_INFO=/run/user/mikus/keyring-sBl4bi/gpg:0:1 TERM=xterm SHELL=/bin/bash ...
rodowisko w pythonie
In [2]: import os print os.environ['VARIABLE'] pewna wartosc
In [3]: print os.environ.keys() ['UPSTART_EVENTS', 'GVM_PLATFORM', 'SHELL', 'XDG_DATA_DIRS', 'MANDATORY_PAT H', 'COMPIZ_CONFIG_PROFILE', 'UPSTART_INSTANCE', 'JOB', 'TEXTDOMAIN', 'LAZY BONES_HOME', 'DESKTOP_AUTOSTART_ID', 'XMODIFIERS', 'JAVA_HOME', 'MFLAGS', ' WORKON_HOME', 'XDG_RUNTIME_DIR', 'XDG_SESSION_ID', 'DBUS_SESSION_BUS_ADDRES S', 'VIRTUALENVWRAPPER_HOOK_DIR', 'DESKTOP_SESSION', 'GTK_MODULES', 'INSTAN CE', 'XDG_MENU_PREFIX', 'LS_COLORS', 'GAIDEN_HOME', 'GNOME_DESKTOP_SESSION_ ID', 'XDG_CURRENT_DESKTOP', 'GRIFFON_HOME', 'USER', 'XDG_VTNR', 'XAUTHORITY ', 'LANGUAGE', 'SESSION_MANAGER', 'SHLVL', 'CLUTTER_IM_MODULE', 'GPG_AGENT_ INFO', 'GVM_VERSION', 'GDMSESSION', 'UPSTART_JOB', 'XDG_SEAT_PATH', 'SPRING BOOT_HOME', '_', 'GTK_IM_MODULE', 'GRAILS_HOME', 'XDG_CONFIG_DIRS', 'UBUNTU _MENUPROXY', 'PAGER', 'QT4_IM_MODULE', 'HOME', 'DISPLAY', 'LANG', 'SESSION' , 'COMP_WORDBREAKS', 'GROOVY_HOME', 'GVM_SERVICE', 'GIT_PAGER', 'GNOME_KEYR ING_PID', 'LESSOPEN', 'LESSCLOSE', 'GVM_INIT', 'VERTX_HOME', 'GVM_DIR', 'MA KELEVEL', 'VIRTUALENVWRAPPER_LOG_DIR', 'GROOVYSERV_HOME', 'LOGNAME', 'XDG_S
EAT', 'GNOME_KEYRING_CONTROL', 'PATH', 'MAKEFLAGS', 'SSH_AGENT_PID', 'TERM' , 'XDG_SESSION_PATH', 'DEFAULTS_PATH', 'SESSIONTYPE', 'IM_CONFIG_PHASE', 'G IO_LAUNCHED_DESKTOP_FILE_PID', 'GIO_LAUNCHED_DESKTOP_FILE', 'SSH_AUTH_SOCK' , 'TEXTDOMAINDIR', 'VARIABLE', 'VIRTUALENVWRAPPER_PROJECT_FILENAME', 'GRADL E_HOME', 'UPSTART_SESSION', 'OLDPWD', 'GDM_LANG', 'CLICOLOR', 'PWD']
Wnioski
Proces potomny dziedziczy rodowisko po rodzicu Rodzice nie widz zmian w rodowiskach procesw potomnych rodowisko mona ustawia explicite
This memo provides information for the Internet community. It does not specify an Internet standard of any kind. Distribution of this memo is unlimited.
Zmienne
AUTH_TYPE, GATEWAY_INTERFACE, CONTENT_LENGTH, CONTENT_TYPE, PATH_INFO, PATH_TRANSLATED, QUERY_STRING, SCRIPT_NAME, REMOTE_ADDR, REMOTE_HOST, REMOTE_IDENT, REMOTE_USER, REQUEST_METHOD, SERVER_NAME, SERVER_PORT, SERVER_PROTOCOL, SERVER_SOFTWARE
Serwer z CGI
Modu standardowej biblioteki Pythona: CGIHTTPServer Serwery HTTP Apache IIS
Lighttpd ...
Serwer laboratoryjny
$ python -m CGIHTTPServer <port> Przykady OSError: [Errno 13] Permission denied
Uruchamianie CGI
Przewanie dedykowany katalog cgi-bin lub rozszerzenie .cgi Odpowiednie uprawnienia r.x dla katalogu ..x dla skryptu / programu #!/usr/bin/env python system musi wiedzie jak uruchomi proces Uruchomienie tak samo jak przez uytkownika: $ cgi-bin/test.py Proces uruchamiany przez uytkownika nobody kwestia bezpieczestwa (eby nie nada za duych uprawnie) Program wykonawczy musi by uruchamialny przez kogokolwiek
Bdy
error.py Informacja w konsoli, ukryta przed uytkownikiem dostp do procesu przez Internet (rwnie dla wszystkich szumowin) informacje o bdach mog by powan luk bezpieczestwa error_debug.py
Ustawianie rodowiska
CGIHTTPServer.run_cgi ... env = copy.deepcopy(os.environ) env['SERVER_SOFTWARE'] = self.version_string() env['SERVER_NAME'] = self.server.server_name env['GATEWAY_INTERFACE'] = 'CGI/1.1' env['SERVER_PROTOCOL'] = self.protocol_version env['SERVER_PORT'] = str(self.server.server_port) env['REQUEST_METHOD'] = self.command uqrest = urllib.unquote(rest) env['PATH_INFO'] = uqrest env['PATH_TRANSLATED'] = self.translate_path(uqrest) env['SCRIPT_NAME'] = scriptname if query: env['QUERY_STRING'] = query ... ua = self.headers.getheader('user-agent') if ua: env['HTTP_USER_AGENT'] = ua ...
ycie CGI
Serwer parsowanie dania ustawienie rodowiska uruchomienie skryptu CGI Skrypt
Serwer
Skrypt odczytanie zmiennych rodowiskowych zbudowanie nagwkw HTTP (w tym Content-Type i Content-Length) wypisanie nagwkw, pustej linii i ciaa na standardowe wyjcie
zbudowanie pierwszej linii odpowiedzi: HTTP/1.1 200 OK odesanie wszystkich danych ze skryptu
Problemy CGI
Kod jest wykonywany w osobnym procesie Kade wywoanie skryptu startuje nowy proces Starowanie nowych procesw jest kosztowne i zuywa zasoby serwera szczeglnie w przypadku jzykw interpretowanych (np. Python)
WSGI
PEP 333 Web Server Gateway Interface Nowy standard (nie implementacja!) dla aplikacji webowych w pythonie Zbir interakcji Pena przenaszalno kodu
Stos
HTTP WSGI Aplikacja
Wymagania WSGI
Serwer Ustawia rodowiska (podobnie jak przy CGI) Dostarcza metod start_response(status, headers, exc_info=None) Buduje odpowied przez wywoanie application(environment, start_response) Zwraca odpowied ze statusem, nagwkami i ciaem
Aplikacja Musi by wywoywalna Pobiera environment i start_response jako parametry wywoania Zwraca obiekt iterowalny lub obiekty typu string (0 lub wicej) stanowice ciao odpowiedzi
Implementacje WSGI
Apache + mod_wsgi
rodowisko WSGI
REQUEST_METHOD, SCRIPT_NAME, PATH_INFO, QUERY_STRING CONTENT_TYPE, CONTENT_LENGTH SERVER_NAME, SERVER_PORT SERVER_PROTOCOL HTTP_* (zmienne odpowiadajce nagwkom) Wyglda znajomo?
uWSGI
uwsgi --http-socket :<port> --plugin python --wsgi-file <script>.wsgi script.ini [uwsgi] plugin = python http-socket = :<port> wsgi-file = <script>.wsgi uwsgi --ini script.ini opcje
nginx + uWSGI
/tmp/<user>.wsgi.sock http://<host>/~<user>/wsgi
script.ini [uwsgi] plugin = python socket = /tmp/<user>.wsgi.sock wsgi-file = <script>.wsgi chmod-socket = 666 master = true daemonize = /tmp/<user>.wsgi.log pidfile = /tmp/<user>.wsgi.pid uwsgi --reload/--stop /tmp/<user>.wsgi.pid
WSGI middleware
Implementacja obu interfejsw (serwera i aplikacji) Dla aplikacji zachowuje si jak serwer Dla serwera zachowuje si jak aplikacja Wzorzec projektowy... ?
In [5]: class Upperware: def __init__(self, app): self.wrapped_app = app def __call__(self, environ, start_response): for data in self.wrapped_app(environ, start_response): yield data.upper()
Uycie
Routing Autentykacja Kontrola cache'a Debugowanie i introspekcja Motywy tematyczne
Podsumowanie
Dynamiczne waciwoci WWW za pomoc osobnych programw Standardy CGI, FastCGI, SCGI, ... WSGI
Osobne procesy rodowisko wykonawcze ze zmiennymi z dania Standardowe wyjcie przesyane jako odpowied