wsgiref — WSGI-Hilfsprogramme und Referenzimplementierung

Quellcode: Lib/wsgiref


Das Web Server Gateway Interface (WSGI) ist eine standardisierte Schnittstelle zwischen Webserver-Software und in Python geschriebenen Webanwendungen. Eine standardisierte Schnittstelle erleichtert die Verwendung einer Anwendung, die WSGI unterstützt, mit einer Reihe verschiedener Webserver.

Nur Entwickler von Webservern und Programmierframeworks müssen jedes Detail und jeden Eckfall des WSGI-Designs kennen. Sie müssen nicht jedes Detail von WSGI verstehen, nur um eine WSGI-Anwendung zu installieren oder eine Webanwendung mit einem vorhandenen Framework zu schreiben.

wsgiref ist eine Referenzimplementierung der WSGI-Spezifikation, die verwendet werden kann, um einem Webserver oder Framework WSGI-Unterstützung hinzuzufügen. Es bietet Hilfsprogramme zur Manipulation von WSGI-Umgebungsvariablen und Antwortheadern, Basisklassen zur Implementierung von WSGI-Servern, einen Demo-HTTP-Server, der WSGI-Anwendungen bedient, Typen für die statische Typprüfung und ein Validierungstool, das WSGI-Server und -Anwendungen auf Konformität mit der WSGI-Spezifikation prüft (PEP 3333).

Siehe wsgi.readthedocs.io für weitere Informationen zu WSGI und Links zu Tutorials und anderen Ressourcen.

wsgiref.util – WSGI-Umgebungshilfsprogramme

Dieses Modul bietet eine Vielzahl von Hilfsfunktionen für die Arbeit mit WSGI-Umgebungen. Eine WSGI-Umgebung ist ein Dictionary, das HTTP-Anfragevariablen enthält, wie in PEP 3333 beschrieben. Alle Funktionen, die einen Parameter environ erwarten, gehen davon aus, dass ein WSGI-konformes Dictionary übergeben wird; siehe bitte PEP 3333 für eine detaillierte Spezifikation und WSGIEnvironment für einen Typalias, der in Typannotationen verwendet werden kann.

wsgiref.util.guess_scheme(environ)

Gibt eine Vermutung zurück, ob wsgi.url_scheme „http“ oder „https“ sein sollte, indem eine Umgebungsvariable HTTPS im environ-Dictionary überprüft wird. Der Rückgabewert ist ein String.

Diese Funktion ist nützlich beim Erstellen eines Gateways, das CGI oder ein CGI-ähnliches Protokoll wie FastCGI umschließt. Typischerweise enthalten Server, die solche Protokolle bereitstellen, eine Variable HTTPS mit dem Wert „1“, „yes“ oder „on“, wenn eine Anfrage über SSL empfangen wird. Daher gibt diese Funktion „https“ zurück, wenn ein solcher Wert gefunden wird, und andernfalls „http“.

wsgiref.util.request_uri(environ, include_query=True)

Gibt die vollständige Anfrage-URI zurück, optional einschließlich der Abfragezeichenfolge, gemäß dem Algorithmus im Abschnitt „URL Reconstruction“ von PEP 3333. Wenn include_query falsch ist, wird die Abfragezeichenfolge nicht in die resultierende URI aufgenommen.

wsgiref.util.application_uri(environ)

Ähnlich wie request_uri(), außer dass die Variablen PATH_INFO und QUERY_STRING ignoriert werden. Das Ergebnis ist die Basis-URI des durch die Anfrage angesprochenen Anwendungsobjekts.

wsgiref.util.shift_path_info(environ)

Verschiebt einen einzelnen Namen von PATH_INFO nach SCRIPT_NAME und gibt den Namen zurück. Das environ-Dictionary wird *in-place* modifiziert; verwenden Sie eine Kopie, wenn Sie PATH_INFO oder SCRIPT_NAME im Originalzustand beibehalten möchten.

Wenn keine Pfadsegmente mehr in PATH_INFO vorhanden sind, wird None zurückgegeben.

Typischerweise wird diese Routine verwendet, um jeden Teil eines Anfrage-URI-Pfads zu verarbeiten, z. B. um den Pfad als eine Reihe von Dictionary-Schlüsseln zu behandeln. Diese Routine modifiziert die übergebene Umgebung, um sie für die Aufrufung einer anderen WSGI-Anwendung, die sich unter der Ziel-URI befindet, geeignet zu machen. Zum Beispiel, wenn eine WSGI-Anwendung unter /foo existiert und der Anfrage-URI-Pfad /foo/bar/baz lautet, und die WSGI-Anwendung unter /foo shift_path_info() aufruft, erhält sie den String „bar“, und die Umgebung wird so aktualisiert, dass sie für die Übergabe an eine WSGI-Anwendung unter /foo/bar geeignet ist. Das heißt, SCRIPT_NAME ändert sich von /foo zu /foo/bar, und PATH_INFO ändert sich von /bar/baz zu /baz.

Wenn PATH_INFO nur ein „/“ ist, gibt diese Routine einen leeren String zurück und hängt einen nachgestellten Schrägstrich an SCRIPT_NAME an, obwohl leere Pfadsegmente normalerweise ignoriert werden und SCRIPT_NAME normalerweise nicht mit einem Schrägstrich endet. Dies ist ein beabsichtigtes Verhalten, um sicherzustellen, dass eine Anwendung den Unterschied zwischen URIs, die auf /x enden, und solchen, die auf /x/ enden, erkennen kann, wenn diese Routine für die Objekt traversal verwendet wird.

wsgiref.util.setup_testing_defaults(environ)

Aktualisiert environ mit trivialen Standardwerten für Testzwecke.

Diese Routine fügt verschiedene Parameter hinzu, die für WSGI erforderlich sind, darunter HTTP_HOST, SERVER_NAME, SERVER_PORT, REQUEST_METHOD, SCRIPT_NAME, PATH_INFO und alle von PEP 3333 definierten wsgi.*-Variablen. Sie liefert nur Standardwerte und ersetzt keine vorhandenen Einstellungen für diese Variablen.

Diese Routine soll es für Unit-Tests von WSGI-Servern und -Anwendungen einfacher machen, Dummy-Umgebungen einzurichten. Sie sollte NICHT von tatsächlichen WSGI-Servern oder -Anwendungen verwendet werden, da die Daten gefälscht sind!

Beispielverwendung (siehe auch demo_app() für ein weiteres Beispiel)

from wsgiref.util import setup_testing_defaults
from wsgiref.simple_server import make_server

# A relatively simple WSGI application. It's going to print out the
# environment dictionary after being updated by setup_testing_defaults
def simple_app(environ, start_response):
    setup_testing_defaults(environ)

    status = '200 OK'
    headers = [('Content-type', 'text/plain; charset=utf-8')]

    start_response(status, headers)

    ret = [("%s: %s\n" % (key, value)).encode("utf-8")
           for key, value in environ.items()]
    return ret

with make_server('', 8000, simple_app) as httpd:
    print("Serving on port 8000...")
    httpd.serve_forever()

Zusätzlich zu den oben genannten Umgebungsfunktionen bietet das Modul wsgiref.util diese weiteren Hilfsmittel

wsgiref.util.is_hop_by_hop(header_name)

Gibt True zurück, wenn ‚header_name‘ ein HTTP/1.1 „Hop-by-Hop“-Header ist, wie in RFC 2616 definiert.

class wsgiref.util.FileWrapper(filelike, blksize=8192)

Eine konkrete Implementierung des Protokolls wsgiref.types.FileWrapper zur Konvertierung eines dateiähnlichen Objekts in einen Iterator. Die resultierenden Objekte sind iterierbar. Während des Iterierens wird der optionale Parameter blksize wiederholt an die read()-Methode des filelike-Objekts übergeben, um Byte-Strings zu erhalten, die zurückgegeben werden. Wenn read() einen leeren Byte-String zurückgibt, wird die Iteration beendet und ist nicht fortsetzbar.

Wenn filelike eine close()-Methode hat, hat das zurückgegebene Objekt ebenfalls eine close()-Methode, und es ruft die close()-Methode des filelike-Objekts auf, wenn es aufgerufen wird.

Beispielverwendung

from io import StringIO
from wsgiref.util import FileWrapper

# We're using a StringIO-buffer for as the file-like object
filelike = StringIO("This is an example file-like object"*10)
wrapper = FileWrapper(filelike, blksize=5)

for chunk in wrapper:
    print(chunk)

Geändert in Version 3.11: Die Unterstützung für die Methode __getitem__() wurde entfernt.

wsgiref.headers – WSGI-Antwortheader-Werkzeuge

Dieses Modul bietet eine einzelne Klasse, Headers, zur bequemen Manipulation von WSGI-Antwortheadern mit einer Mapping-ähnlichen Schnittstelle.

class wsgiref.headers.Headers([headers])

Erstellt ein Mapping-ähnliches Objekt, das headers umschließt, welches eine Liste von Header-Namen/Wert-Tupeln sein muss, wie in PEP 3333 beschrieben. Der Standardwert für headers ist eine leere Liste.

Headers-Objekte unterstützen typische Mapping-Operationen einschließlich __getitem__(), get(), __setitem__(), setdefault(), __delitem__() und __contains__(). Für jede dieser Methoden ist der Schlüssel der Header-Name (case-insensitiv behandelt) und der Wert ist der erste Wert, der diesem Header-Namen zugeordnet ist. Das Setzen eines Headers löscht alle vorhandenen Werte für diesen Header und fügt dann einen neuen Wert am Ende der umschlossenen Header-Liste hinzu. Die bestehende Reihenfolge von Headern wird im Allgemeinen beibehalten, wobei neue Header am Ende der umschlossenen Liste hinzugefügt werden.

Im Gegensatz zu einem Dictionary lösen Headers-Objekte keinen Fehler aus, wenn Sie versuchen, einen Schlüssel abzurufen oder zu löschen, der nicht in der umschlossenen Header-Liste vorhanden ist. Das Abrufen eines nicht vorhandenen Headers gibt einfach None zurück, und das Löschen eines nicht vorhandenen Headers tut nichts.

Headers-Objekte unterstützen auch die Methoden keys(), values() und items(). Die von keys() und items() zurückgegebenen Listen können denselben Schlüssel mehrmals enthalten, wenn ein mehrwertiger Header vorhanden ist. Die Länge eines Headers-Objekts ist gleich der Länge seiner items(), was wiederum gleich der Länge der umschlossenen Header-Liste ist. Tatsächlich gibt die Methode items() einfach eine Kopie der umschlossenen Header-Liste zurück.

Das Aufrufen von bytes() auf einem Headers-Objekt gibt einen formatierten Byte-String zurück, der für die Übertragung als HTTP-Antwortheader geeignet ist. Jeder Header wird mit seinem Wert in einer Zeile platziert, getrennt durch einen Doppelpunkt und ein Leerzeichen. Jede Zeile wird mit einem Wagenrücklauf und Zeilenvorschub abgeschlossen, und der Byte-String wird mit einer leeren Zeile beendet.

Zusätzlich zu ihrer Mapping-Oberfläche und Formatierungsfunktionen verfügen Headers-Objekte über die folgenden Methoden zum Abfragen und Hinzufügen von mehrwertigen Headern sowie zum Hinzufügen von Headern mit MIME-Parametern

get_all(name)

Gibt eine Liste aller Werte für den benannten Header zurück.

Die zurückgegebene Liste wird in der Reihenfolge sortiert, in der sie im ursprünglichen Header-Liste erschienen oder dieser Instanz hinzugefügt wurden, und kann Duplikate enthalten. Gelöschte und neu eingefügte Felder werden immer am Ende der Header-Liste angehängt. Wenn keine Felder mit dem angegebenen Namen existieren, wird eine leere Liste zurückgegeben.

add_header(name, value, **_params)

Fügt einen (möglicherweise mehrwertigen) Header mit optionalen MIME-Parametern hinzu, die über Schlüsselwortargumente angegeben werden.

name ist das hinzuzufügende Header-Feld. Schlüsselwortargumente können verwendet werden, um MIME-Parameter für das Header-Feld festzulegen. Jeder Parameter muss ein String oder None sein. Unterstriche in Parameternamen werden in Bindestriche umgewandelt, da Bindestriche in Python-Bezeichnern ungültig sind, aber viele MIME-Parameternamen Bindestriche enthalten. Wenn der Parameterwert ein String ist, wird er den Headerwertparametern in der Form name="value" hinzugefügt. Wenn er None ist, wird nur der Parametername hinzugefügt. (Dies wird für MIME-Parameter ohne Wert verwendet.) Beispielverwendung

h.add_header('content-disposition', 'attachment', filename='bud.gif')

Das Obige fügt einen Header hinzu, der wie folgt aussieht

Content-Disposition: attachment; filename="bud.gif"

Geändert in Version 3.5: Der Parameter headers ist optional.

wsgiref.simple_server – ein einfacher WSGI-HTTP-Server

Dieses Modul implementiert einen einfachen HTTP-Server (basierend auf http.server), der WSGI-Anwendungen bedient. Jede Serverinstanz bedient eine einzelne WSGI-Anwendung auf einem bestimmten Host und Port. Wenn Sie mehrere Anwendungen auf einem einzigen Host und Port bedienen möchten, sollten Sie eine WSGI-Anwendung erstellen, die PATH_INFO parst, um auszuwählen, welche Anwendung für jede Anfrage aufgerufen werden soll. (Z. B. unter Verwendung der Funktion shift_path_info() aus wsgiref.util.)

wsgiref.simple_server.make_server(host, port, app, server_class=WSGIServer, handler_class=WSGIRequestHandler)

Erstellt einen neuen WSGI-Server, der auf host und port lauscht und Verbindungen für app akzeptiert. Der Rückgabewert ist eine Instanz der übergebenen server_class und verarbeitet Anfragen mit der angegebenen handler_class. app muss ein WSGI-Anwendungsobjekt sein, wie in PEP 3333 definiert.

Beispielverwendung

from wsgiref.simple_server import make_server, demo_app

with make_server('', 8000, demo_app) as httpd:
    print("Serving HTTP on port 8000...")

    # Respond to requests until process is killed
    httpd.serve_forever()

    # Alternative: serve one request, then exit
    httpd.handle_request()
wsgiref.simple_server.demo_app(environ, start_response)

Diese Funktion ist eine kleine, aber vollständige WSGI-Anwendung, die eine Textseite mit der Nachricht „Hello world!“ und einer Liste der im environ-Parameter bereitgestellten Schlüssel/Wert-Paare zurückgibt. Sie ist nützlich, um zu überprüfen, ob ein WSGI-Server (wie wsgiref.simple_server) eine einfache WSGI-Anwendung korrekt ausführen kann.

Der aufrufbare start_response sollte dem Protokoll StartResponse folgen.

class wsgiref.simple_server.WSGIServer(server_address, RequestHandlerClass)

Erstellt eine WSGIServer-Instanz. server_address sollte ein (host,port)-Tupel sein, und RequestHandlerClass sollte die Unterklasse von http.server.BaseHTTPRequestHandler sein, die zur Verarbeitung von Anfragen verwendet wird.

Sie müssen diesen Konstruktor normalerweise nicht aufrufen, da die Funktion make_server() alle Details für Sie erledigen kann.

WSGIServer ist eine Unterklasse von http.server.HTTPServer, daher sind alle seine Methoden (wie serve_forever() und handle_request()) verfügbar. WSGIServer bietet auch diese WSGI-spezifischen Methoden

set_app(application)

Legt die aufrufbare application als die WSGI-Anwendung fest, die Anfragen empfangen wird.

get_app()

Gibt die aktuell festgelegte aufrufbare Anwendung zurück.

Normalerweise müssen Sie diese zusätzlichen Methoden jedoch nicht verwenden, da set_app() normalerweise von make_server() aufgerufen wird, und get_app() hauptsächlich zum Nutzen von Anforderungshandler-Instanzen existiert.

class wsgiref.simple_server.WSGIRequestHandler(request, client_address, server)

Erstellt einen HTTP-Handler für die gegebene request (d. h. einen Socket), client_address (ein (host,port)-Tupel) und server (WSGIServer-Instanz).

Sie müssen keine Instanzen dieser Klasse direkt erstellen; sie werden automatisch nach Bedarf von WSGIServer-Objekten erstellt. Sie können diese Klasse jedoch unterklassifizieren und sie als handler_class an die Funktion make_server() übergeben. Einige möglicherweise relevante Methoden für das Überschreiben in Unterklassen

get_environ()

Gibt ein WSGIEnvironment-Dictionary für eine Anfrage zurück. Die Standardimplementierung kopiert den Inhalt des Dictionary-Attributs base_environ des WSGIServer-Objekts und fügt dann verschiedene Header hinzu, die aus der HTTP-Anfrage abgeleitet werden. Jeder Aufruf dieser Methode sollte ein neues Dictionary zurückgeben, das alle relevanten CGI-Umgebungsvariablen gemäß PEP 3333 enthält.

get_stderr()

Gibt das Objekt zurück, das als wsgi.errors-Stream verwendet werden soll. Die Standardimplementierung gibt einfach sys.stderr zurück.

handle()

Verarbeitet die HTTP-Anfrage. Die Standardimplementierung erstellt eine Handlerinstanz unter Verwendung einer Klasse aus wsgiref.handlers, um die eigentliche WSGI-Schnittstelle zu implementieren.

wsgiref.validate — WSGI-Konformitätsprüfer

Beim Erstellen neuer WSGI-Anwendungsobjekte, Frameworks, Server oder Middleware kann es nützlich sein, die Konformität des neuen Codes mit wsgiref.validate zu validieren. Dieses Modul stellt eine Funktion bereit, die WSGI-Anwendungsobjekte erstellt, die die Kommunikation zwischen einem WSGI-Server oder Gateway und einem WSGI-Anwendungsobjekt validieren, um beide Seiten auf Protokollkonformität zu prüfen.

Beachten Sie, dass dieses Hilfsprogramm keine vollständige PEP 3333-Konformität garantiert; das Fehlen von Fehlern in diesem Modul bedeutet nicht zwangsläufig, dass keine Fehler vorhanden sind. Wenn dieses Modul jedoch einen Fehler ausgibt, ist es praktisch sicher, dass entweder der Server oder die Anwendung nicht zu 100 % konform ist.

Dieser Wrapper basiert auf dem Modul paste.lint aus Ian Bickings „Python Paste“-Bibliothek.

wsgiref.validate.validator(application)

Umschließt application und gibt ein neues WSGI-Anwendungsobjekt zurück. Die zurückgegebene Anwendung leitet alle Anfragen an die ursprüngliche application weiter und prüft, ob sowohl die application als auch der sie aufrufende Server dem WSGI-Spezifikation und RFC 2616 entsprechen.

Jede erkannte Nichtkonformität führt zum Auslösen einer AssertionError; beachten Sie jedoch, dass die Handhabung dieser Fehler serverspezifisch ist. Zum Beispiel geben wsgiref.simple_server und andere auf wsgiref.handlers basierende Server (die die Fehlerbehandlungsroutinen nicht überschreiben, um etwas anderes zu tun) einfach eine Meldung aus, dass ein Fehler aufgetreten ist, und geben den Traceback nach sys.stderr oder einen anderen Fehlerstrom aus.

Dieser Wrapper kann auch Ausgaben über das Modul warnings generieren, um fragwürdige Verhaltensweisen anzuzeigen, die jedoch möglicherweise nicht tatsächlich durch PEP 3333 verboten sind. Sofern sie nicht über Python-Befehlszeilenoptionen oder die API von warnings unterdrückt werden, werden solche Warnungen nach sys.stderr geschrieben ( *nicht* nach wsgi.errors, es sei denn, sie sind zufällig dasselbe Objekt).

Beispielverwendung

from wsgiref.validate import validator
from wsgiref.simple_server import make_server

# Our callable object which is intentionally not compliant to the
# standard, so the validator is going to break
def simple_app(environ, start_response):
    status = '200 OK'  # HTTP Status
    headers = [('Content-type', 'text/plain')]  # HTTP Headers
    start_response(status, headers)

    # This is going to break because we need to return a list, and
    # the validator is going to inform us
    return b"Hello World"

# This is the application wrapped in a validator
validator_app = validator(simple_app)

with make_server('', 8000, validator_app) as httpd:
    print("Listening on port 8000....")
    httpd.serve_forever()

wsgiref.handlers – Server/Gateway-Basisklassen

Dieses Modul bietet Basis-Handlerklassen für die Implementierung von WSGI-Servern und -Gateways. Diese Basisklassen kümmern sich um den Großteil der Arbeit bei der Kommunikation mit einer WSGI-Anwendung, solange sie eine CGI-ähnliche Umgebung sowie Ein-, Ausgabe- und Fehlerströme erhalten.

class wsgiref.handlers.CGIHandler

CGI-basierte Invokation über sys.stdin, sys.stdout, sys.stderr und os.environ. Dies ist nützlich, wenn Sie eine WSGI-Anwendung haben und diese als CGI-Skript ausführen möchten. Rufen Sie einfach CGIHandler().run(app) auf, wobei app das WSGI-Anwendungsobjekt ist, das Sie aufrufen möchten.

Diese Klasse ist eine Unterklasse von BaseCGIHandler, die wsgi.run_once auf true, wsgi.multithread auf false und wsgi.multiprocess auf true setzt und immer sys und os verwendet, um die notwendigen CGI-Streams und die Umgebung zu erhalten.

class wsgiref.handlers.IISCGIHandler

Eine spezialisierte Alternative zu CGIHandler, zur Verwendung bei der Bereitstellung auf dem IIS-Webserver von Microsoft, ohne die Konfigurationsoption allowPathInfo (IIS>=7) oder Metabase allowPathInfoForScriptMappings (IIS<7) gesetzt zu haben.

Standardmäßig gibt IIS ein PATH_INFO zurück, das dem SCRIPT_NAME vorne vorangestellt ist, was zu Problemen für WSGI-Anwendungen führt, die Routing implementieren möchten. Dieser Handler entfernt einen solchen duplizierten Pfad.

IIS kann so konfiguriert werden, dass das korrekte PATH_INFO übergeben wird, dies führt jedoch zu einem weiteren Fehler, bei dem PATH_TRANSLATED falsch ist. Glücklicherweise wird diese Variable selten verwendet und ist nicht durch WSGI garantiert. Unter IIS<7 kann die Einstellung jedoch nur auf Vhost-Ebene vorgenommen werden, was sich auf alle anderen Skriptzuordnungen auswirkt, von denen viele fehlschlagen, wenn sie dem PATH_TRANSLATED-Fehler ausgesetzt sind. Aus diesem Grund wird IIS<7 fast nie mit der Korrektur bereitgestellt (selbst IIS7 verwendet sie selten, da es immer noch keine Benutzeroberfläche dafür gibt).

Es gibt keine Möglichkeit für CGI-Code, festzustellen, ob die Option gesetzt wurde, daher wird eine separate Handlerklasse bereitgestellt. Sie wird auf die gleiche Weise wie CGIHandler verwendet, d.h. durch Aufrufen von IISCGIHandler().run(app), wobei app das WSGI-Anwendungsobjekt ist, das Sie aufrufen möchten.

Hinzugefügt in Version 3.2.

class wsgiref.handlers.BaseCGIHandler(stdin, stdout, stderr, environ, multithread=True, multiprocess=False)

Ähnlich wie CGIHandler, verwendet aber anstelle der Module sys und os die explizit angegebenen CGI-Umgebungs- und I/O-Streams. Die Werte für multithread und multiprocess werden verwendet, um die Flags wsgi.multithread und wsgi.multiprocess für alle von der Handlerinstanz ausgeführten Anwendungen zu setzen.

Diese Klasse ist eine Unterklasse von SimpleHandler und ist für die Verwendung mit Software vorgesehen, die keine HTTP-„Origin-Server“ sind. Wenn Sie eine Gateway-Protokollimplementierung (wie CGI, FastCGI, SCGI usw.) schreiben, die einen Status:-Header zum Senden eines HTTP-Status verwendet, sollten Sie wahrscheinlich diese anstelle von SimpleHandler untererben.

class wsgiref.handlers.SimpleHandler(stdin, stdout, stderr, environ, multithread=True, multiprocess=False)

Ähnlich wie BaseCGIHandler, aber für die Verwendung mit HTTP-Origin-Servern konzipiert. Wenn Sie eine HTTP-Serverimplementierung schreiben, möchten Sie wahrscheinlich diese anstelle von BaseCGIHandler untererben.

Diese Klasse ist eine Unterklasse von BaseHandler. Sie überschreibt die Methoden __init__(), get_stdin(), get_stderr(), add_cgi_vars(), _write() und _flush(), um das explizite Setzen der Umgebung und der Streams über den Konstruktor zu unterstützen. Die übergebenen Umgebungs- und Streamvariablen werden in den Attributen stdin, stdout, stderr und environ gespeichert.

Die write()-Methode von stdout sollte jeden Block vollständig schreiben, wie io.BufferedIOBase.

class wsgiref.handlers.BaseHandler

Dies ist eine abstrakte Basisklasse zum Ausführen von WSGI-Anwendungen. Jede Instanz behandelt eine einzelne HTTP-Anfrage, obwohl Sie prinzipiell eine Unterklasse erstellen könnten, die für mehrere Anfragen wiederverwendbar ist.

BaseHandler-Instanzen haben nur eine Methode, die für die externe Verwendung bestimmt ist

run(app)

Führen Sie die angegebene WSGI-Anwendung, app, aus.

Alle anderen Methoden von BaseHandler werden von dieser Methode im Prozess der Ausführung der Anwendung aufgerufen und existieren daher hauptsächlich, um die Anpassung des Prozesses zu ermöglichen.

Die folgenden Methoden MÜSSEN in einer Unterklasse überschrieben werden

_write(data)

Puffern Sie die Bytes data zur Übertragung an den Client. Es ist in Ordnung, wenn diese Methode die Daten tatsächlich überträgt; BaseHandler trennt Schreib- und Flush-Operationen nur zur größeren Effizienz, wenn das zugrunde liegende System tatsächlich eine solche Unterscheidung hat.

_flush()

Erzwingen Sie die Übertragung gepufferter Daten an den Client. Es ist in Ordnung, wenn diese Methode eine No-Op ist (d.h. wenn _write() die Daten tatsächlich sendet).

get_stdin()

Gibt ein Objekt zurück, das mit InputStream kompatibel ist und als wsgi.input der gerade verarbeiteten Anfrage verwendet werden kann.

get_stderr()

Gibt ein Objekt zurück, das mit ErrorStream kompatibel ist und als wsgi.errors der gerade verarbeiteten Anfrage verwendet werden kann.

add_cgi_vars()

Fügt CGI-Variablen für die aktuelle Anfrage in das Attribut environ ein.

Hier sind einige andere Methoden und Attribute, die Sie möglicherweise überschreiben möchten. Diese Liste ist jedoch nur eine Zusammenfassung und enthält nicht jede überschreibbare Methode. Sie sollten die Docstrings und den Quellcode für zusätzliche Informationen konsultieren, bevor Sie versuchen, eine angepasste BaseHandler-Unterklasse zu erstellen.

Attribute und Methoden zur Anpassung der WSGI-Umgebung

wsgi_multithread

Der Wert, der für die Umgebungsvariable wsgi.multithread verwendet werden soll. Er ist standardmäßig true in BaseHandler, kann aber in den anderen Unterklassen eine andere Standardeinstellung haben (oder vom Konstruktor gesetzt werden).

wsgi_multiprocess

Der Wert, der für die Umgebungsvariable wsgi.multiprocess verwendet werden soll. Er ist standardmäßig true in BaseHandler, kann aber in den anderen Unterklassen eine andere Standardeinstellung haben (oder vom Konstruktor gesetzt werden).

wsgi_run_once

Der Wert, der für die Umgebungsvariable wsgi.run_once verwendet werden soll. Er ist standardmäßig false in BaseHandler, aber CGIHandler setzt ihn standardmäßig auf true.

os_environ

Die Standard-Umgebungsvariablen, die in die WSGI-Umgebung jeder Anfrage aufgenommen werden sollen. Standardmäßig ist dies eine Kopie von os.environ zu dem Zeitpunkt, als wsgiref.handlers importiert wurde, aber Unterklassen können ihre eigenen auf Klassen- oder Instanzebene erstellen. Beachten Sie, dass das Dictionary als schreibgeschützt betrachtet werden sollte, da der Standardwert zwischen mehreren Klassen und Instanzen geteilt wird.

server_software

Wenn das Attribut origin_server gesetzt ist, wird der Wert dieses Attributs verwendet, um die Standard-Umgebungsvariable SERVER_SOFTWARE und auch einen Standard-Server:-Header in HTTP-Antworten zu setzen. Er wird für Handler (wie BaseCGIHandler und CGIHandler) ignoriert, die keine HTTP-Origin-Server sind.

Geändert in Version 3.3: Der Begriff „Python“ wird durch implementierungsspezifische Begriffe wie „CPython“, „Jython“ usw. ersetzt.

get_scheme()

Gibt das für die aktuelle Anfrage verwendete URL-Schema zurück. Die Standardimplementierung verwendet die Funktion guess_scheme() aus wsgiref.util, um zu erraten, ob das Schema „http“ oder „https“ sein sollte, basierend auf den Umgebungsvariablen der aktuellen Anfrage.

setup_environ()

Setzt das Attribut environ auf eine vollständig aufgefüllte WSGI-Umgebung. Die Standardimplementierung verwendet alle oben genannten Methoden und Attribute, plus die Methoden get_stdin(), get_stderr() und add_cgi_vars() sowie das Attribut wsgi_file_wrapper. Außerdem fügt es einen Schlüssel SERVER_SOFTWARE ein, falls dieser nicht vorhanden ist, solange das Attribut origin_server einen wahren Wert hat und das Attribut server_software gesetzt ist.

Methoden und Attribute zur Anpassung der Ausnahmebehandlung

log_exception(exc_info)

Protokolliert das exc_info-Tupel im Serverprotokoll. exc_info ist ein Tupel (type, value, traceback). Die Standardimplementierung schreibt den Traceback einfach in den wsgi.errors-Stream der Anfrage und leert ihn. Unterklassen können diese Methode überschreiben, um das Format zu ändern, die Ausgabe umzuleiten, den Traceback per E-Mail an einen Administrator zu senden oder andere geeignete Maßnahmen zu ergreifen.

traceback_limit

Die maximale Anzahl von Frames, die in Tracebacks enthalten sein sollen, die von der Standardmethode log_exception() ausgegeben werden. Wenn None, werden alle Frames eingeschlossen.

error_output(environ, start_response)

Diese Methode ist eine WSGI-Anwendung, um eine Fehlerseite für den Benutzer zu generieren. Sie wird nur aufgerufen, wenn ein Fehler auftritt, bevor Header an den Client gesendet werden.

Diese Methode kann über sys.exception() auf den aktuellen Fehler zugreifen und sollte diese Informationen an start_response übergeben, wenn diese aufgerufen wird (wie im Abschnitt „Fehlerbehandlung“ von PEP 3333 beschrieben). Insbesondere sollte der start_response-Callable dem StartResponse-Protokoll folgen.

Die Standardimplementierung verwendet einfach die Attribute error_status, error_headers und error_body, um eine Ausgabeseite zu generieren. Unterklassen können dies überschreiben, um dynamischere Fehlerausgaben zu erzeugen.

Beachten Sie jedoch, dass es aus Sicherheitssicht nicht empfohlen wird, Diagnosen an beliebige Benutzer weiterzugeben. Idealerweise müssten Sie etwas Besonderes tun, um die Diagnoseausgabe zu aktivieren, weshalb die Standardimplementierung keine enthält.

error_status

Der HTTP-Status, der für Fehlerantworten verwendet wird. Dies sollte ein Statusstring sein, wie in PEP 3333 definiert; er ist standardmäßig ein 500er-Code und eine Nachricht.

error_headers

Die HTTP-Header, die für Fehlerantworten verwendet werden. Dies sollte eine Liste von WSGI-Antwortheadern sein ((name, value)-Tupel), wie in PEP 3333 beschrieben. Die Standardliste setzt den Content-Type nur auf text/plain.

error_body

Der Fehlerantwortkörper. Dies sollte ein Bytestring einer HTTP-Antwort sein. Standardmäßig ist dies der Klartext: „A server error occurred. Please contact the administrator.“

Methoden und Attribute für die Funktion „Optional Platform-Specific File Handling“ von PEP 3333

wsgi_file_wrapper

Ein wsgi.file_wrapper-Factory, kompatibel mit wsgiref.types.FileWrapper, oder None. Der Standardwert dieses Attributs ist die Klasse wsgiref.util.FileWrapper.

sendfile()

Überschreiben Sie dies, um plattformspezifische Dateiübertragung zu implementieren. Diese Methode wird nur aufgerufen, wenn der Rückgabewert der Anwendung eine Instanz der durch das Attribut wsgi_file_wrapper angegebenen Klasse ist. Sie sollte einen wahren Wert zurückgeben, wenn die Datei erfolgreich übertragen wurde, sodass der Standard-Übertragungscode nicht ausgeführt wird. Die Standardimplementierung dieser Methode gibt einfach einen falschen Wert zurück.

Verschiedene Methoden und Attribute

origin_server

Dieses Attribut sollte auf einen wahren Wert gesetzt werden, wenn die Methoden _write() und _flush() des Handlers direkt mit dem Client kommunizieren, anstatt über ein CGI-ähnliches Gateway-Protokoll, das den HTTP-Status in einem speziellen Header Status: erwartet.

Der Standardwert dieses Attributs ist true in BaseHandler, aber false in BaseCGIHandler und CGIHandler.

http_version

Wenn origin_server true ist, wird dieses String-Attribut verwendet, um die HTTP-Version der an den Client gesendeten Antwort festzulegen. Es ist standardmäßig "1.0".

wsgiref.handlers.read_environ()

Wandelt CGI-Variablen aus os.environ in PEP 3333 „bytes in unicode“-Strings um und gibt ein neues Dictionary zurück. Diese Funktion wird von CGIHandler und IISCGIHandler anstelle der direkten Verwendung von os.environ verwendet, was nicht unbedingt WSGI-konform auf allen Plattformen und Webservern mit Python 3 ist – insbesondere auf denen, bei denen die tatsächliche Umgebung des Betriebssystems Unicode ist (z. B. Windows) oder bei denen die Umgebung Bytes sind, aber die vom System verwendete Kodierung von Python zum Dekodieren etwas anderes als ISO-8859-1 ist (z. B. Unix-Systeme mit UTF-8).

Wenn Sie selbst einen CGI-basierten Handler implementieren, möchten Sie diese Routine wahrscheinlich anstelle des direkten Kopierens von Werten aus os.environ verwenden.

Hinzugefügt in Version 3.2.

wsgiref.types – WSGI-Typen für statische Typüberprüfung

Dieses Modul stellt verschiedene Typen für die statische Typüberprüfung bereit, wie in PEP 3333 beschrieben.

Hinzugefügt in Version 3.11.

class wsgiref.types.StartResponse

Ein typing.Protocol, das start_response()-Aufrufe (PEP 3333) beschreibt.

wsgiref.types.WSGIEnvironment

Ein Typalias, der ein WSGI-Umgebungsdictionary beschreibt.

wsgiref.types.WSGIApplication

Ein Typalias, der einen WSGI-Anwendungs-Callable beschreibt.

class wsgiref.types.InputStream

Ein typing.Protocol, der einen WSGI Input Stream beschreibt.

class wsgiref.types.ErrorStream

Ein typing.Protocol, der einen WSGI Error Stream beschreibt.

class wsgiref.types.FileWrapper

Ein typing.Protocol, der einen File Wrapper beschreibt. Siehe wsgiref.util.FileWrapper für eine konkrete Implementierung dieses Protokolls.

Beispiele

Dies ist eine funktionierende „Hello World“-WSGI-Anwendung, bei der der start_response-Callable dem StartResponse-Protokoll folgen sollte

"""
Every WSGI application must have an application object - a callable
object that accepts two arguments. For that purpose, we're going to
use a function (note that you're not limited to a function, you can
use a class for example). The first argument passed to the function
is a dictionary containing CGI-style environment variables and the
second variable is the callable object.
"""
from wsgiref.simple_server import make_server


def hello_world_app(environ, start_response):
    status = "200 OK"  # HTTP Status
    headers = [("Content-type", "text/plain; charset=utf-8")]  # HTTP Headers
    start_response(status, headers)

    # The returned object is going to be printed
    return [b"Hello World"]

with make_server("", 8000, hello_world_app) as httpd:
    print("Serving on port 8000...")

    # Serve until process is killed
    httpd.serve_forever()

Beispiel für eine WSGI-Anwendung, die das aktuelle Verzeichnis bedient, wobei optionale Verzeichnisse und Portnummern (Standard: 8000) auf der Kommandozeile akzeptiert werden

"""
Small wsgiref based web server. Takes a path to serve from and an
optional port number (defaults to 8000), then tries to serve files.
MIME types are guessed from the file names, 404 errors are raised
if the file is not found.
"""
import mimetypes
import os
import sys
from wsgiref import simple_server, util


def app(environ, respond):
    # Get the file name and MIME type
    fn = os.path.join(path, environ["PATH_INFO"][1:])
    if "." not in fn.split(os.path.sep)[-1]:
        fn = os.path.join(fn, "index.html")
    mime_type = mimetypes.guess_file_type(fn)[0]

    # Return 200 OK if file exists, otherwise 404 Not Found
    if os.path.exists(fn):
        respond("200 OK", [("Content-Type", mime_type)])
        return util.FileWrapper(open(fn, "rb"))
    else:
        respond("404 Not Found", [("Content-Type", "text/plain")])
        return [b"not found"]


if __name__ == "__main__":
    # Get the path and port from command-line arguments
    path = sys.argv[1] if len(sys.argv) > 1 else os.getcwd()
    port = int(sys.argv[2]) if len(sys.argv) > 2 else 8000

    # Make and start the server until control-c
    httpd = simple_server.make_server("", port, app)
    print(f"Serving {path} on port {port}, control-C to stop")
    try:
        httpd.serve_forever()
    except KeyboardInterrupt:
        print("Shutting down.")
        httpd.server_close()