LWAN ist ein Hochleistungs- und skalierbarer Webserver.
Die Projektwebsite enthält weitere Details.
| Betriebssystem | Bogen | Freigeben | Debuggen | Statische Analyse | Tests |
|---|---|---|---|---|---|
| Linux | x86_64 | Berichtsgeschichte | |||
| Freebsd 14 | x86_64 | ||||
| OpenBSD 7.4 | x86_64 |
Sie können entweder Lwan selbst erstellen, ein Containerbild verwenden oder ein Paket aus Ihrer Lieblingsverteilung holen.
Stellen Sie vor der Installation von LWAN sicher, dass alle Abhängigkeiten installiert sind. Alle von ihnen sind häufige Abhängigkeiten in jeder GNU/Linux -Verteilung; Paketnamen sind unterschiedlich, aber es sollte nicht schwierig sein, mit dem von Ihrer Verteilung verwendeten Paket -Management -Tool zu suchen.
Das Build -System sucht nach diesen Bibliotheken und aktiviert/links, falls verfügbar.
-DENABLE_BROTLI=NO übergeben werden kann-DENABLE_ZSTD=NO bestanden werden kann-DENABLE_TLS=ON (Standard) übergeben wird:-DUSE_ALTERNATIVE_MALLOC übergeben werden:pacman -S cmake zlibpkg install cmake pkgconfapt-get update && apt-get install git cmake zlib1g-dev pkg-configbrew install cmake pacman -S cmake zlib sqlite luajit mariadb-libs gperftools valgrind mbedtlspkg install cmake pkgconf sqlite3 lua51apt-get update && apt-get install git cmake zlib1g-dev pkg-config lua5.1-dev libsqlite3-dev libmariadb-dev libmbedtls-devbrew install cmake mariadb-connector-c sqlite [email protected] pkg-config ~$ git clone git://github.com/lpereira/lwan
~$ cd lwan
~/lwan$ mkdir build
~/lwan$ cd build
Auswählen einer Release -Version (keine Debugging -Symbole, Nachrichten, einige Optimierungen usw.):
~/lwan/build$ cmake .. -DCMAKE_BUILD_TYPE=Release
Wenn Sie Optimierungen aktivieren möchten, aber dennoch einen Debugger verwenden möchten, verwenden Sie dies stattdessen:
~/lwan/build$ cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo
Optimierungen zu deaktivieren und eine debuggierfreundlichere Version zu erstellen:
~/lwan/build$ cmake .. -DCMAKE_BUILD_TYPE=Debug
~/lwan/build$ make
Dies erzeugt ein paar Binärdateien:
src/bin/lwan/lwan : Die wichtigste LWAN -ausführbare Datei. Kann mit --help für Anleitung ausgeführt werden.src/bin/testrunner/testrunner : Enthält Code zur Ausführung der Testsuite ( src/scripts/testsuite.py ).src/samples/freegeoip/freegeoip : FreeGoIP -Beispielimplementierung. Benötigt SQLite.src/samples/techempower/techempower : Code für den TechEmpower Web Framework Benchmark. Benötigt SQLite- und Mariadb -Bibliotheken.src/samples/clock/clock : Taktprobe. Generiert eine GIF -Datei, die immer die lokale Zeit zeigt.src/bin/tools/mimegen : Erstellt die Tabelle zum Erweiterungsmime. Verwendet während des Build -Prozesses.src/bin/tools/bin2hex : Generiert eine C -Datei aus einer Binärdatei, die für die Verwendung mit #include geeignet ist. Verwendet während des Build -Prozesses.src/bin/tools/configdump : Dumpelt eine Konfigurationsdatei mit der Konfigurationsleser -API. Zum Testen verwendet.src/bin/tools/weighttp : Schreiben Sie das weighttp HTTP -Benchmarking -Tool neu.src/bin/tools/statuslookupgen : Generiert eine perfekte Hash -Tabelle für HTTP -Statuscodes und deren Beschreibungen. Verwendet während des Build -Prozesses. Das Bestehen -DCMAKE_BUILD_TYPE=Release ermöglicht einige Compiler -Optimierungen (wie LTO) und den Code für die aktuelle Architektur ein.
Wichtig
Bitte verwenden Sie den Release -Build beim Benchmarking . Die Standardeinstellung ist der Debug -Build, der nicht nur alle Anforderungen an die Standardausgabe protokolliert, sondern auch beim Halten eines Schlosses und den Server stark gedrückt bleibt.
Das Standardaufbau (dh nicht übergeben -DCMAKE_BUILD_TYPE=Release ) erstellt eine Version, die für Debugging -Zwecke geeignet ist. Diese Version kann unter Valgrind verwendet werden (falls ihre Header vorhanden sind) und enthält Debugging -Nachrichten, die in der Versionsversion entzogen sind. Für jede Anfrage werden Debugging -Nachrichten gedruckt.
Bei diesen Builds können Desinfektionsmittel aktiviert werden. Um auszuwählen, mit welchem LWAN eine der folgenden Optionen für die CMake -Invocation -Zeile angeben soll:
-DSANITIZER=ubsan wählt das undefinierte Desinfektionsmittel aus.-DSANITIZER=address wählt das Desinfektionsmittel der Adressen aus.-DSANITIZER=thread Wählt den Thread Desinfektionsmittel aus. Alternative Speicherallocatoren können ebenfalls ausgewählt werden. LWAN unterstützt derzeit TcMalloc, Mimalloc und Jemalloc. Um eines von ihnen zu verwenden, übergeben Sie -DALTERNATIVE_MALLOC=name an die CMAKE -Invocation -Zeile unter Verwendung der Namen "Optionale Abhängigkeiten".
Die Option -DUSE_SYSLOG=ON kann an CMAKE übergeben werden, um neben der Standardausgabe auch das Systemprotokoll zu protokollieren.
Wenn Sie LWAN für eine Verteilung bauen, ist es möglicherweise ratsam, die Option -DMTUNE_NATIVE=OFF zu verwenden, da die generierte Binärdatei auf einigen Computern möglicherweise nicht ausgeführt wird.
Der TLS -Support wird automatisch in Gegenwart einer geeigneten MBETTLS -Installation auf Linux -Systemen mit Headern aktiviert, die neu genug sind, um KTLs zu unterstützen, kann jedoch deaktiviert werden, indem Sie -DENABLE_TLS=NO an CMAKE übergeben werden.
~/lwan/build$ make testsuite
Dadurch wird das testrunner -Programm kompiliert und die Regressionstestsuite in src/scripts/testsuite.py ausgeführt.
~/lwan/build$ make benchmark
Dadurch wird testrunner kompiliert und das Benchmark -Skript src/scripts/benchmark.py ausgeführt.
LWAN kann auch mit dem Deckungsbautyp erstellt werden, indem -DCMAKE_BUILD_TYPE=Coverage angegeben werden. Auf diese Weise ermöglicht die generate-coverage , mit dem testrunner einen Testabdeckungsbericht mit LCOV erstellt.
Jedes Commit in diesem Repository löst die Erzeugung dieses Berichts aus, und die Ergebnisse sind öffentlich verfügbar.
Richten Sie den Server durch Bearbeiten des bereitgestellten lwan.conf ein; Das Format wird im Folgenden im Folgenden erläutert.
Notiz
LWAN wird versuchen, eine Konfigurationsdatei zu finden, die im ausführbaren Namen im aktuellen Verzeichnis basiert. testrunner.conf wird für den testrunner binären lwan.conf für die lwan binäre und so weiter verwendet.
Konfigurationsdateien werden aus dem aktuellen Verzeichnis geladen. Wenn keine Änderungen an dieser Datei vorgenommen werden, wird das Ausführen von LWAN statische Dateien im Verzeichnis ./wwwroot bereitgestellt. Lwan wird an allen Schnittstellen auf Port 8080 zuhören.
LWAN erfasst die Anzahl der CPUs, erhöht die maximale Anzahl offener Dateideskriptoren und versucht im Allgemeinen das Beste, um angemessene Einstellungen für die Umgebung zu automatisieren, auf der sie ausgeführt wird. Viele dieser Einstellungen können in der Konfigurationsdatei optimiert werden, aber es ist in der Regel eine gute Idee, sich nicht mit ihnen anzulegen.
Tipp
Optional kann die lwan -Binärdatei für eine statische One-Shot-Datei ohne Konfigurationsdatei verwendet werden. Führen Sie es mit --help für Hilfe aus.
LWAN verwendet eine vertraute key = value -Konfigurationsdateisyntax. Kommentare werden mit dem # Charakter unterstützt (ähnlich wie EG -Shell -Skripte, Python und Perl). Verschachtelte Abschnitte können mit lockigen Klammern erstellt werden. Abschnitte können leer sein; In diesem Fall sind lockige Klammern optional.
some_key_name entspricht some key name in Konfigurationsdateien (als Implementierungsdetail werden die Konfigurationsoptionen für Codelese -Konfigurationen nur mit Unterstrichen angegeben).
Tipp
Werte können Umgebungsvariablen enthalten. Verwenden Sie die Syntax ${VARIABLE_NAME} . Standardwerte können mit einem Dickdarm angegeben werden (z. B. ${VARIABLE_NAME:foo} , der an ${VARIABLE_NAME} bewertet wird, wenn es festgelegt ist, oder ansonsten foo ).
sound volume = 11 # This one is 1 louder
playlist metal {
files = '''
/multi/line/strings/are/supported.mp3
/anything/inside/these/are/stored/verbatim.mp3
'''
}
playlist chiptune {
files = """
/if/it/starts/with/single/quotes/it/ends/with/single/quotes.mod
/but/it/can/use/double/quotes.s3m
"""
}
Einige Beispiele finden Sie in lwan.conf und techempower.conf .
Konstanten können in der gesamten Konfigurationsdatei definiert und wiederverwendet werden, indem sie in einem constants überall in der Konfigurationsdatei angeben. Eine Konstante wird erst verfügbar sein, nachdem dieser Abschnitt eine bestimmte Konstante definiert. Konstanten können neu definiert werden. Wenn eine Konstante nicht definiert ist, wird ihr Wert aus einer Umgebungsvariablen erhalten. Wenn es in einem Abschnitt eines constants oder in der Umgebung nicht definiert ist, wird LWAN mit einer entsprechenden Fehlermeldung abbrechen.
constants {
user_name = ${USER}
home_directory = ${HOME}
buffer_size = 1000000
}
Die gleiche Syntax für die oben angegebenen Standardwerte ist hier gültig (z. B. user_name als ${USER:nobody} setzt ${user_name} auf nobody , wenn ${USER} nicht in die Umgebungsvariable festgelegt ist oder keine andere Konstante ist.)
| Typ | Beschreibung |
|---|---|
str | Jede Art von Freiformtext, normalerweise anwendungsspezifisch |
int | Ganzzahlnummer. Bereich ist anwendungsspezifisch |
time | Zeitintervall. Siehe Tabelle unten für Einheiten |
bool | Boolescher Wert. In der Tabelle unten finden Sie gültige Werte |
Zeitfelder können mit Multiplikatoren angegeben werden. Multiple kann angegeben werden, sie sind nur addiert. Zum Beispiel gibt "1m 1W" "1 Monat und 1 Woche" (37 Tage) an. In der folgenden Tabelle werden alle bekannten Multiplikatoren aufgeführt:
| Multiplikator | Beschreibung |
|---|---|
s | Sekunden |
m | Minuten |
h | Std |
d | Tage |
w | 7-Tage-Wochen |
M | 30-Tage-Monate |
y | 365-tägige Jahre |
Notiz
Eine Zahl mit einem Multiplikator in dieser Tabelle wird ignoriert. Eine Warnung wird beim Lesen der Konfigurationsdatei ausgestellt. Es dürfen keine Räume zwischen der Anzahl und ihrem Multiplikator bestehen.
| Wahre Werte | Falsche Werte |
|---|---|
| Jede ganzzahlige Nummer anders als 0 | 0 |
on | off |
true | false |
yes | no |
Im Allgemeinen ist es eine gute Idee, Lwan die besten Einstellungen für Ihre Umgebung zu entscheiden. Nicht jede Umgebung ist jedoch gleich, und nicht alle Verwendungen können automatisch entschieden werden, sodass einige Konfigurationsoptionen bereitgestellt werden.
| Option | Typ | Standard | Beschreibung |
|---|---|---|---|
keep_alive_timeout | time | 15 | Zeitüberschreitung, um eine Verbindung am Leben zu erhalten |
quiet | bool | false | Legen Sie auf True fest, um keine Debugging -Nachrichten zu drucken. Nur wirksam in Release -Builds. |
expires | time | 1M 1w | Wert des "Ablauf" -Headers. Der Standard ist 1 Monat und 1 Woche |
threads | int | 0 | Anzahl der E/O -Threads. Standard (0) ist die Anzahl der Online -CPUs |
proxy_protocol | bool | false | Aktiviert das Proxy -Protokoll. Die Versionen 1 und 2 werden unterstützt. Aktivieren Sie diese Einstellung nur, wenn Sie LWAN hinter einem Proxy verwenden, und der Proxy unterstützt dieses Protokoll. Andernfalls ermöglicht dies jedem, Ursprungs -IP -Adressen zu fälschen |
max_post_data_size | int | 40960 | Legt die maximale Anzahl von Datengröße für Postanforderungen in Bytes fest |
max_put_data_size | int | 40960 | Legt die maximale Anzahl von Datengröße für Put -Anforderungen in Bytes fest |
max_file_descriptors | int | 524288 | Maximale Anzahl der Dateideskriptoren. Muss mindestens 10x threads sein |
request_buffer_size | int | 4096 | Puffergrößenlänge anfordern. Wenn es größer als der Standard von 4096 ist, wird es dynamisch zugewiesen. |
allow_temp_files | str | "" | Temporäre Dateien verwenden; Setzen Sie auf Post -Anfragen post , um Anfragen oder all (gleichbedeutend mit der Einstellung zu post put ) für beides put . |
error_template | str | Standardfehlervorlage | Vorlage für Fehlercodes. Siehe Variablen unten. |
error_template| Variable | Typ | Beschreibung |
|---|---|---|
short_message | str | Kurze Fehlermeldung (zB Not found ) |
long_message | str | Lange Fehlermeldung (z. B. The requested resource could not be found on this server ) |
Lwan kann seine Berechtigungen an einen Benutzer im System abgeben und seine Dateisystemansicht mit einem Chroot einschränken. Dies ist zwar nicht kugelsicher, aber dies bietet eine erste Sicherheitsebene für den Fall, dass in Lwan einen Fehler vorhanden ist.
Um diese Funktion zu verwenden, deklarieren Sie eine straitjacket (oder straightjacket ) und stellen Sie einige Optionen fest. Dies erfordert, dass Lwan als root ausgeführt wird.
Obwohl dieser Abschnitt überall in der Datei geschrieben werden kann (solange es sich um eine Deklaration auf höchster Ebene handelt), wird Lwan aufgrund des EG -Instanziierens des Moduls serve_files sich weigern, zu starten. (Dieser Scheck wird nur unter Linux als Schutz für Malkonfiguration durchgeführt.)
Tipp
Deklarieren Sie eine StraitJacket direkt vor einem site -Abschnitt, so dass Konfigurationsdateien und private Daten (z. B. TLS -Schlüssel) nach der Initialisierung außerhalb der Reichweite des Servers sind.
| Option | Typ | Standard | Beschreibung |
|---|---|---|---|
user | str | NULL | Lassen Sie den Benutzernamen Berechtigungen abgeben |
chroot | str | NULL | Weg zu chroot() |
drop_capabilities | bool | true | Lassen Sie alle Funktionen mit Capset (2) (unter Linux) oder verpflichten (2) (unter OpenBSD). |
Wenn für jede Antwort benutzerdefinierte Header angeben müssen, kann man einen headers -Abschnitt im globalen Bereich deklarieren. Die Reihenfolge, die dieser Abschnitt erscheint, ist nicht wichtig.
Zum Beispiel diese Erklärung:
headers {
Server = Apache/1.0.0 or nginx/1.0.0 (at your option)
Some-Custom-Header = ${WITH_THIS_ENVIRONMENT_VARIABLE}
}
Wird beide den Server überschreiben ( Server: lwan wird nicht gesendet) und setzen Some-Custom-Header mit dem Wert, der aus der Umgebungsvariablen $WITH_THIS_ENVIRONMENT_VARIABLE erhalten wird.
Einige Header können nicht außer Kraft gesetzt werden, da dies beim Senden ihrer tatsächlichen Werte bei der Wartung von Anfragen Probleme verursachen würde. Dazu gehören, aber nicht beschränkt auf:
DateExpiresWWW-AuthenticateConnectionContent-TypeTransfer-EncodingAccess-Control-Allow- Header Notiz
Headernamen sind ebenfalls unempfindlich (und Fallversicherung). Überschreibender SeRVeR überschreibt den Server -Header, sendet ihn jedoch so, wie er in der Konfigurationsdatei geschrieben wurde.
Laut LWAN -Prozess werden nur zwei Hörer unterstützt: der HTTP -Listener (Abschnitt listener ) und der HTTPS -Listener (Abschnitt tls_listener ). Nur ein Zuhörer jedes Typs ist erlaubt.
Warnung
TLS -Unterstützung ist experimentell. Obwohl es während der ersten Tests stabil ist, kann Ihre Kilometerleistung variieren. Zu diesem Zeitpunkt wird nur TLSV1.2 unterstützt, aber TLSV1.3 ist geplant.
Notiz
TLS -Unterstützung erfordert? Linux mit dem integrierten oder geladenen tls.ko -Modul. Die Unterstützung für andere Betriebssysteme kann in Zukunft hinzugefügt werden. FreeBSD scheint möglich zu sein, andere Betriebssysteme scheinen keine ähnliche Funktionen zu bieten. Für nicht unterstützte Betriebssysteme ist die Verwendung eines TLS -Terminator -Proxy wie Hitch eine gute Option.
Sowohl für listener als auch für tls_listener -Abschnitte ist der einzige Parameter die Schnittstellenadresse und den Port, das Sie anhören müssen. Die Listener -Syntax ist ${ADDRESS}:${PORT} , wobei ${ADDRESS} entweder * (Bindung an alle Schnittstellen), eine IPv6 -Adresse (falls von quadratischen Klammern umgeben), eine IPv4 -Adresse oder ein Hostname sein kann. Zum Beispiel würde listener localhost:9876 nur in der lo -Schnittstelle, Port 9876 , zuhören.
Während ein listener Abschnitt keine Schlüssel nimmt, erfordert ein tls_listener -Abschnitt zwei: cert und key (jeweils Zeige, auf den Speicherort auf der Festplatte, an dem sich das TLS-Zertifikat und die privaten Schlüsseldateien befinden) und nimmt eine optionale Boolesche hsts Taste an, die steuern, wenn Strict-Transport-Security auf HTTPS-Antworten gesendet werden.
Tipp
openssl req -nodes -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -sha256 -days 7 generieren Sie diese Schlüssel zu Testzwecken
Notiz
Es wird empfohlen, dass eine StraitJacket mit einer chroot -Option direkt nach einem tls_listener -Abschnitt so deklariert wird, dass die Pfade zu dem Zertifikat und der Schlüssel ab diesem Zeitpunkt unerreichbar sind.
Wenn die Systemd -Socket -Aktivierung verwendet wird, kann systemd als Parameter angegeben werden. (Wenn mehrere Hörer von Systemd angegeben sind, kann systemd:FileDescriptorName angegeben werden, wobei FileDescriptorName den in der systemd.socket -Dokumentation festgelegten Konventionen folgt.)
Beispiele:
listener *:8080 # Listen on all interfaces, port 8080, HTTP
tls_listener *:8081 { # Listen on all interfaces, port 8081, HTTPS
cert = /path/to/cert.pem
key = /path/to/key.pem
}
# Use named systemd socket activation for HTTP listener
listener systemd:my-service-http.socket
# Use named systemd socket activation for HTTPS listener
tls_listener systemd:my-service-https.socket {
...
}
Ein site -Abschnitt gruppiert Instanzen von Modulen und Handlern, die auf Anfragen an ein bestimmtes URL -Präfix reagieren.
Um URLs zu leiten, entspricht LWAN mit einem Satz von Präfixen, die im Abschnitt Hörer angegeben wurden, mit einem Satz von Präfixen. Wie eine Anfrage an ein bestimmtes Präfix behandelt wird, hängt davon ab, welcher Handler oder Modul im Abschnitt Hörer deklariert wurde. Handler und Module sind intern ähnlich; Handler sind lediglich Funktionen und halten keinen Zustand, und die Module halten den Zustand (benannte Instanz). Mehrere Instanzen eines Moduls können in einem Hörerbereich angezeigt werden.
Es gibt keine spezielle Syntax, um ein Präfix an einem Handler oder Modul anzubringen. Alle hier gelten Konfigurationssparregeln gelten hier. Verwenden Sie ${NAME} ${PREFIX} , um den ${PREFIX} Präfix -Pfad mit einem Handler mit dem Namen ${NAME} (wenn ${NAME} mit & , wie mit Cs "Adresse" "Operator) oder ein Modul mit dem Namen ${NAME} zu verknüpfen. Hier können leere Abschnitte verwendet werden.
Jedes Modul hat seine spezifischen Optionen und sie sind in den nächsten Abschnitten aufgeführt. Zusätzlich zu den Konfigurationsoptionen kann in der Erklärung einer Modulinstanz ein spezieller authorization vorhanden sein. Handler nehmen keine Konfigurationsoptionen an, können jedoch den Abschnitt authorization enthalten.
Tipp
Durch die Ausführung von LWAN mit dem Argument --help -HELP" wird eine Liste integrierter Module und Handler angezeigt.
Im Folgenden finden Sie einige grundlegende Dokumentationen für die mit LWAN verschifften Module.
Das Modul serve_files serviert statische Dateien und erstellt automatisch Verzeichnisindizes oder diente vorab komprimierte Dateien. Es wird im Allgemeinen sein Bestes geben, um Dateien nach einigen Heuristiken auf schnellstmögliche Weise zu servieren.
| Option | Typ | Standard | Beschreibung |
|---|---|---|---|
path | str | NULL | Pfad zu einem Verzeichnis, das Dateien enthält, die zugestellt werden sollen |
index_path | str | index.html | Dateiname, der als Index für ein Verzeichnis dient |
serve_precompressed_path | bool | true | Wenn $ file.gz existiert, ist kleiner und neuer als $ Datei, und der Client akzeptiert die gzip -Codierung, übertragen Sie es |
auto_index | bool | true | Generieren Sie eine Verzeichnisliste automatisch, wenn keine index_path -Datei vorhanden ist. Ansonsten liefert 404 |
auto_index_readme | bool | true | Enthält den Inhalt von Readme -Dateien als Teil des automatisch generierten Verzeichnisindex |
directory_list_template | str | NULL | Pfad zu einer Schnurrbartvorlage für die Verzeichnisliste; Verwenden Sie standardmäßig eine interne Vorlage |
read_ahead | int | 131702 | Maximale Menge an Bytes zum Vorausschnitt beim Zwischenspeichern von Dateien. Ein Wert von 0 deaktiviert Readahead. Readahead wird mit einem Thread mit niedriger Priorität durchgeführt, um die E/A -Threads nicht zu blockieren, während die Dateiausdehnung aus dem Dateisystem gelesen werden. |
cache_for | time | 5s | Zeit, um Dateimetadaten (Größe, komprimierte Inhalte, Dateideskriptor geöffnet) im Cache zu halten |
Notiz
Dateien, die kleiner als 16 kib sind, werden für die in der Einstellung cache_for angegebene Dauer in RAM komprimiert. LWAN wird immer versuchen, mit Deflate zu komprimieren und komprimieren optional mit Brotli und ZSTD (wenn LWAN mit ordnungsgemäßer Unterstützung gebaut wurde).
In Fällen, in denen die Komprimierung den Aufwand nicht wert wäre (z. B. das Hinzufügen des Content-Encoding Headers würde zu einer größeren Antwort führen, als die unkomprimierte Datei zu senden, normalerweise für sehr kleine Dateien), verbringt LWAN keine Zeit damit, eine Datei zu komprimieren.
Bei Dateien, die größer als 16 kib sind, wird LWAN nicht versuchen, sie zu komprimieren. In zukünftigen Versionen kann dies dies tun und Antworten mithilfe von Chunked-Codierung senden, während die Datei komprimiert wird (bis zu einer bestimmten Grenze), aber vorerst werden nur vorab komprimierte Dateien (siehe serve_precompressed_path in der obigen Tabelle) berücksichtigt.
In allen Fällen könnte LWAN versuchen, die GZIP -Version zu verwenden, wenn dies im Dateisystem gefunden wird, und der Client hat diese Codierung angefordert.
directory_list_template| Variable | Typ | Beschreibung |
|---|---|---|
rel_path | str | Pfad relativ zum Wurzelverzeichnis Realer Pfad |
readme | str | Inhalt der First ReadMe -Datei gefunden ( readme , readme.txt , read.me , README.TXT , README ) |
file_list | Iterator | Iterate auf der Dateiliste |
file_list.zebra_class | str | odd für seltsame Gegenstände oder even oder sogar Artikel |
file_list.icon | str | Pfad zum Symbol für den Dateityp |
file_list.name | str | Dateiname (entkommen) |
file_list.type | str | Dateityp (Verzeichnis oder reguläre Datei) |
file_list.size | int | Dateigröße |
file_list.unit | str | Einheit für file_size |
Das lua -Modul ermöglicht es, Anfragen durch Skripte, die in der LUA -Programmiersprache geschrieben wurden, bedient zu werden. Obwohl die von diesem Modul bereitgestellte Funktionalität ziemlich spartanisch ist, kann es Frameworks wie Sailor ausführen.
Skripte können aus Dateien oder in die Konfigurationsdatei eingebettet werden, und die Ergebnisse des Ladens, die Standard -LUA -Module und (optional, wenn sie Luajit verwendet), wird die Optimierung des Codes für eine Weile zwischengespeichert.
| Option | Typ | Standard | Beschreibung |
|---|---|---|---|
default_type | str | text/plain | Standardmime-Typ für Antworten |
script_file | str | NULL | Weg zum Lua -Skript |
cache_period | time | 15s | Zeit, den LUA -Zustand im Speicher geladen zu halten |
script | str | NULL | Inline Lua -Skript |
Notiz
LuA -Skripte können keine globalen Variablen verwenden, da sie möglicherweise nicht nur von verschiedenen Threads bedient werden, sondern der Status nur für die in der Option cache_period konfiguration angegebene Zeit verfügbar ist. Dies liegt daran, dass jeder E/A -Thread in LWAN eine Instanz eines Lua -VM (dh eine lua_State -Struktur für jeden E/A -Thread) erzeugt, und jede Lwan Coroutine wird einen Lua -Thread (mit lua_newthread() ) pro Anfrage hervorbringen.
Für jeden Endpunkt besteht keine Instanz des LUA -Moduls. Ein einzelnes Skript, das in die Konfigurationsdatei eingebettet oder auf andere Weise eingebettet ist, kann viele verschiedene Endpunkte bedienen. Skripte sollen Funktionen mit der folgenden Signatur implementieren: handle_${METHOD}_${ENDPOINT}(req) , wobei ${METHOD} eine HTTP -Methode sein kann (dh get , post , head usw.) und ${ENDPOINT} ist der gewünschte Endpunkt, der von dieser Funktion behandelt werden muss. Eine generische Funktion handle(req) wird aufgerufen, wenn die spezifische Version nicht vorhanden ist.
Tipp
Verwenden Sie den root für einen Catchall. Beispielsweise wird die Handler -Funktion handle_get_root() aufgerufen, wenn für diese Anfrage kein anderer Handler gefunden werden kann. Wenn kein Catchall angegeben ist, gibt der Server einen 404 Not Found Fehler zurück.
Der req -Parameter verweist auf ein Metatable, das Methoden enthält, um Informationen aus der Anforderung zu erhalten oder die Antwort festzulegen, wie unten angegeben:
req:query_param(param) gibt den Abfrageparameter (aus der Abfragezeichenfolge) mit dem param oder nil zurück, falls dies nicht gefunden wirdreq:post_param(param) gibt den Postparameter (nur für ${POST} Handler) mit dem param zurück oder nil falls dies nicht gefunden wirdreq:set_response(str) legt die Antwort auf die Zeichenfolge str festreq:say(str) sendet einen Antwortanteil (unter Verwendung von Chunked -Codierung in HTTP)req:send_event(event, str) sendet ein Ereignis (unter Verwendung von Server-Sent-Ereignissen)req:cookie(param) gibt den Cookie namens param zurück, oder nil ist nicht gefundenreq:set_headers(tbl) stellt die Antwortheader aus der Tabelle tbl fest. Ein Header kann im Tabellenwert mehrmals mit einer Tabelle anstelle einer Zeichenfolge angegeben werden ( {'foo'={'bar', 'baz'}} ); muss angerufen werden, bevor eine Antwort mit say() oder send_event() gesendet wirdreq:header(name) erhält den Header aus der Anfrage mit dem angegebenen Namen oder nil falls dies nicht gefunden wirdreq:sleep(ms) macht den aktuellen Handler für die angegebene Menge an Millisekunden paustreq:ws_upgrade() gibt 1 zurück, wenn die Verbindung auf ein WebSocket aktualisiert werden könnte. 0 sonstreq:ws_write_text(str) sendet str über die WebSocket-Upgraded-Verbindung als Textrahmenreq:ws_write_binary(str) sendet str über die WebSocket-Upgraded-Verbindung als Binärrahmenreq:ws_write(str) sendet str über die WebSocket-Upgraded-Verbindung als Text oder Binärrahmen, abhängig von Inhalten, die nur ASCII-Zeichen enthalten oder nichtreq:ws_read() gibt eine Zeichenfolge mit dem Inhalt des letzten Websocket -Frame oder einer Nummer zurück, die einen Status angibt (Enotconn/107 unter Linux, wenn es getrennt wurde; Eagain/11 auf Linux, wenn nichts verfügbar ist; Enomsg/42 auf Linux sonst). Der Rückgabewert hier könnte sich in Zukunft für etwas LUA-ähnliches ändern.req:remote_address() gibt eine Zeichenfolge mit der Remote -IP -Adresse zurück.req:path() gibt eine Zeichenfolge mit dem Anforderungspfad zurück.req:query_string() gibt eine Zeichenfolge mit der Abfragezeichenfolge zurück (leere Zeichenfolge, wenn keine Abfragezeichenfolge vorhanden ist).req:body() gibt die Anforderungsbehörde zurück (Post/Put -Anforderungen).req:request_id() Gibt eine Zeichenfolge zurück, die die Anforderungs -ID enthält.req:request_date() gibt das Datum zurück, wie er im Date geschrieben wird.req:is_https() gibt true zurück, wenn diese Anfrage über https, ansonsten false gewartet wird.req:host() gibt den Wert des Host -Headers zurück, falls vorhanden, ansonsten nil .req:http_version() gibt HTTP/1.0 oder HTTP/1.1 je nach Anforderungsversion zurück.req:http_method() gibt eine Zeichenfolge in Großbuchstaben mit der HTTP -Methode zurück (z. B. "GET" ).req:http_headers() gibt eine Tabelle mit allen Header und ihren Werten zurück. Handlerfunktionen können entweder nil zurückgeben (in diesem Fall wird eine 200 OK -Antwort generiert) oder eine Zahl, die einem HTTP -Statuscode entspricht. Der Versuch, einen ungültigen HTTP -Statuscode oder etwas anderes als eine Nummer oder nil zurückzugeben, führt zu einer 500 Internal Server Error .
Zusätzlich zu den Metamethods im req -Parameter kann man auch Nachrichten mit unterschiedlichen Protokollierungsstufen protokollieren, indem sie Methoden von Lwan.log aufrufen:
Lwan.log:warning(str)Lwan.log:info(str)Lwan.log:error(str)Lwan.log:critical(str) (wird auch Lwan abbrechen! Verwendung mit Vorsicht)Lwan.log:debug(str) (nur in Debug-Builds erhältlich; nein, sonst) Notiz
Wenn LWAN mit Syslog -Support erstellt wird, werden diese Nachrichten auch an das Systemprotokoll gesendet, andernfalls werden sie auf den Standardfehler gedruckt.
Das rewrite -Modul entspricht den Mustern in URLs und gibt die Option, entweder zu einer anderen URL umzuleiten oder die Anfrage so umzuschreiben, dass LWAN die Anfrage so behandelt, als würde es ursprünglich so gestellt.
Notiz
Aus der LUA 5.3.1 gegabelt, ist die regelmäßige Expression möglicherweise nicht so featurziert wie die meisten allgemeinen Motoren, wurde jedoch speziell ausgewählt, da es sich um einen deterministischen endlichen Automaten handelt, um einige Arten von Denial-of-Service-Angriffen unmöglich zu machen.
Die neue URL kann unter Verwendung einer einfachen Textsubstitutionssyntax oder Verwendung von LuA -Skripten angegeben werden.
Tipp
LuA -Skripte enthalten die gleichen Metamethods, die im vom LuA -Modul bereitgestellten req -Metatable verfügbar sind, sodass es ziemlich leistungsfähig sein kann.
Für jede Instanz des Umschreibens erfordert ein pattern und die Aktion, die ausgeführt werden muss, wenn ein solches Muster übereinstimmt. Muster werden in der Reihenfolge bewertet, die sie in der Konfigurationsdatei angezeigt werden, und werden unter Verwendung von verschachtelten Abschnitten in der Konfigurationsdatei angegeben. Betrachten Sie beispielsweise das folgende Beispiel, in dem zwei Muster angegeben werden:
rewrite /some/base/endpoint {
pattern posts/(%d+) {
# Matches /some/base/endpointposts/2600 and /some/base/endpoint/posts/2600
rewrite_as = /cms/view-post?id=%1
}
pattern imgur/(%a+)/(%g+) {
# Matches /some/base/endpointimgur/gif/mpT94Ld and /some/base/endpoint/imgur/gif/mpT94Ld
redirect_to = https://i.imgur.com/%2.%1
}
}
In diesem Beispiel wird zwei Muster definiert, die eine schönere URL bereitstellen, die dem Benutzer versteckt ist, und eine andere Möglichkeit, einen direkten Link zu einem auf einem beliebten Image -Hosting -Dienst gehosteten Bild zu erhalten (dh Anfrage /some/base/endpoint/imgur/mp4/4kOZNYX wird direkt in einen Ressource im IMGUR -Dienst umgeleitet).
Der Wert von rewrite_as oder redirect_to kann auch Lua -Skripte sein; In diesem Fall muss die Option expand_with_lua auf true eingestellt werden, und anstatt die einfache Textersubstitutionssyntax als Beispiel oben zu verwenden, muss stattdessen eine Funktion namens handle_rewrite(req, captures) definiert werden. Der req -Parameter ist im Abschnitt LUA -Modul dokumentiert. Der Parameter captures ist eine Tabelle, die alle Aufnahmen enthält (dh captures[2] in der einfachen Textersubstitionssyntax in %2 entspricht). Diese Funktion gibt die neue URL zurück, um sich umzuleiten.
Dieses Modul hat keine Optionen für sich. Optionen werden in jedem Muster angegeben.
| Option | Typ | Standard | Beschreibung |
|---|---|---|---|
rewrite_as | str | NULL | Schreiben Sie die URL nach diesem Muster neu |
redirect_to | str | NULL | Den neuen URL nach diesem Muster umleiten |
expand_with_lua | bool | false | Verwenden Sie LUA -Skripte, um eine Anforderung umzuleiten oder umzuschreiben |
Die Optionen redirect_to und rewrite_as schließen sich gegenseitig aus, und einer von ihnen muss zumindest angegeben werden.
Es ist auch möglich, Bedingungen anzugeben, um ein Umschreiben auszulösen. Öffnen Sie um einen condition zu öffnen, geben Sie den Zustandstyp und dann die Parameter für diese zu bewertende Bedingung an. Mehrere Bedingungen können pro Umschreiben -Regel festgelegt werden, solange eine Bedingung pro Typ vorliegt:
| Zustand | Kann Subst verwenden. Syntax | Abschnitt erforderlich | Parameter | Beschreibung |
|---|---|---|---|---|
cookie | Ja | Ja | Ein einzelner key = value | Überprüfungen, wenn die Anforderung Cookie key aufweist, hat value |
query | Ja | Ja | Ein einzelner key = value | Überprüfungen Wenn die Anforderung key enthält, hat der Wertwert value |
post | Ja | Ja | Ein einzelner key = value | Überprüft, ob die Anforderung den key aufweist, hat value |
header | Ja | Ja | Ein einzelner key = value | Überprüft, ob der Anforderungs -Header key value hat |
environment | Ja | Ja | Ein einzelner key = value | Überprüft, ob key des Umgebungsvariablen den value hat |
stat | Ja | Ja | path , is_dir , is_file | Überprüft, ob path im Dateisystem vorliegt, und optional überprüft, ob is_dir oder is_file |
encoding | NEIN | Ja | deflate , gzip , brotli , zstd , none | Überprüft, ob der Client Antworten in einer festgelegten Codierung akzeptiert (z. B. deflate = yes für die Deflate -Codierung) |
proxied | NEIN | NEIN | Boolean | Überprüfungen, wenn die Anfrage über Proxy -Protokoll vorgenommen wurde |
http_1.0 | NEIN | NEIN | Boolean | Schecks, wenn die Anfrage mit einem HTTP/1.0 -Client gestellt wird |
is_https | NEIN | NEIN | Boolean | Überprüfungen, wenn die Anfrage über HTTPS gestellt wird |
has_query_string | NEIN | NEIN | Boolean | Überprüft, ob die Anforderung eine Abfragezeichenfolge hat (auch wenn sie leer sind) |
method | NEIN | NEIN | Methodenname | Überprüft, ob die HTTP -Methode die angegeben ist |
lua | NEIN | NEIN | Saite | Läuft die LUA -Funktion matches(req) innerhalb der String und prüft, ob sie true oder false zurückgibt |
backref | NEIN | Ja | Ein einzelner backref index = value | Überprüft, ob die BackRef -Nummer mit dem angegebenen Wert übereinstimmt |
Kann Subst verwenden. Die Syntax bezieht sich auf die Fähigkeit, das übereinstimmende Muster mit derselben Substitutionssyntax zu verweisen, die für das rewrite as redirect to Aktionen verwendet wird. Zum Beispiel wird condition cookie { some-cookie-name = foo-%1-bar } %1 durch die erste Übereinstimmung des Musters ersetzen, mit dem diese Bedingung zusammenhängt.
Notiz
Bedingungen, für die kein Abschnitt erforderlich ist, müssen als Schlüssel geschrieben werden. Zum Beispiel ist condition has_query_string = yes .
Wenn man beispielsweise site-dark-mode.css senden möchte, wenn es einen style Cookie mit dem Wert dark gibt, und ansonsten site-light-mode.css senden kann, kann man schreiben:
pattern site.css {
rewrite as = /site-dark-mode.css
condition cookie { style = dark }
}
pattern site.css {
rewrite as = /site-light-mode.css
}
Ein weiteres Beispiel: Wenn man vorab komprimierte Dateien senden möchte, wenn sie im Dateisystem vorhanden sind und der Benutzer sie angefordert hat:
pattern (%g+) {
condition encoding { brotli = yes }
condition stat { path = %1.brotli }
rewrite as = %1.brotli
}
pattern (%g+) {
condition encoding { gzip = yes }
condition stat { path = %1.gzip }
rewrite as = %1.gzip
}
pattern (%g+) {
condition encoding { zstd = yes }
condition stat { path = %1.zstd }
rewrite as = %1.zstd
}
pattern (%g+) {
condition encoding { deflate = yes }
condition stat { path = %1.deflate }
rewrite as = %1.deflate
}
Notiz
Im Allgemeinen ist dies nicht erforderlich, da das Datei -Serving -Modul dies automatisch erledigt und die kleinste Datei auswählt, die für die angeforderte Codierung verfügbar ist. Dies zeigt jedoch, dass es möglich ist, eine ähnliche Funktion durch Konfiguration zu haben.
Das redirect generiert, wie es in der Dose heißt, eine 301 Moved permanently (standardmäßige Zeit; der Code kann geändert werden, siehe unten) gemäß den in seiner Konfiguration angegebenen Optionen. Im Allgemeinen sollte das rewrite stattdessen verwendet werden, da es mehr Funktionen verpackt. Dieses Modul dient jedoch auch als Beispiel für das Schreiben von LWAN -Modulen (weniger als 100 Codezeilen).
Wenn die to nicht angegeben ist, generiert sie immer eine 500 Internal Server Error . Wenn Sie einen ungültigen HTTP -Code oder einen Code angeben, von dem LWAN nicht weiß (siehe enum lwan_http_status ), wird eine 301 Moved Permanently Reaktion erzeugt.
| Option | Typ | Standard | Beschreibung |
|---|---|---|---|
to | str | NULL | Die Lage, sich um zu leiten, um zu leiten |
code | int | 301 | Der HTTP -Code zur Durchführung einer Weiterleitung |
Das response generiert eine künstliche Reaktion eines jeden HTTP -Code. Zusätzlich zum Beispiel für das Schreiben eines LWAN -Moduls kann es verwendet werden, um Hohlräume aus anderen Modulen herauszuarbeiten (zB generiert eine 405 Not Allowed Antwort für Dateien in /.git , wenn / mit dem Modul serve_files serviert wird).
Wenn der mitgelieferte code außerhalb der von LWAN bekannten Antwortcodes fällt, wird stattdessen ein 404 Not Found Fehler gesendet.
| Option | Typ | Standard | Beschreibung |
|---|---|---|---|
code | int | 999 | Ein HTTP -Antwortcode |
Die fastcgi -Modulproxiesanfragen zwischen dem HTTP -Client, der mit LWAN eine Verbindung zu LWAN herstellt, und einem von LWAN zugegriffenen FastCGI -Server. Dies ist zum Beispiel nützlich, um Seiten einer Skriptsprache wie PHP zu servieren.
Notiz
Dies ist eine vorläufige Version dieses Moduls, und als solches ist es nicht gut optimiert, einige Funktionen fehlen und einige der Umgebung sind hartcodiert.
| Option | Typ | Standard | Beschreibung |
|---|---|---|---|
address | str | Adresse an eine Verbindung zu. Kann ein Dateipfad (für UNIX -Domain -Sockets), eine IPv4 -Adresse ( aaa.bbb.ccc.ddd:port ) oder IPv6 -Adresse ( [...]:port ) sein. | |
script_path | str | Ort, an dem sich die CGI -Skripte befinden. | |
default_index | str | index.php | Standardskript zum Ausführen, wenn sie in der Anforderung URI nicht spezifiziert werden. |
Autorisierungsabschnitte können in einer Modulinstanz oder Handlerin deklariert werden und bieten eine Möglichkeit, die Erfüllung dieser Anfrage durch den Standard -Mechanismus des Standard -HTTP -Autorisierungsmechanismus zu genehmigen. Um eine Autorisierung zu verlangen, um auf eine bestimmte Modulinstanz oder einen bestimmten Handler zuzugreifen, deklarieren Sie einen authorization mit einem basic Parameter und setzen Sie eine seiner Optionen fest.
| Option | Typ | Standard | Beschreibung |
|---|---|---|---|
realm | str | Lwan | Reich für die Autorisierung. Dies wird normalerweise in der Benutzer-/Passwort -Benutzeroberfläche in Browsern angezeigt |
password_file | str | NULL | Pfad für eine Datei mit Benutzername und Kennwörtern (im klaren Text). Das Dateiformat entspricht dem von LWAN verwendeten Konfigurationsdateiformat |
Warnung
Kennwörter werden nicht nur in einer Datei in einer Datei gelöscht, auf die vom Server zugegriffen werden sollte, sondern werden auch einige Sekunden im Speicher gehalten. Vermeiden Sie diese Funktion, wenn möglich.
Bitte lesen Sie diesen Abschnitt (und folgen Sie ihm), wenn Sie vorhaben, zu LWAN beizutragen. Hier gibt es nichts Unerwartetes; Dies folgt hauptsächlich den Regeln und Erwartungen vieler anderer Foss -Projekte, aber jeder erwartet, dass die Dinge ein bisschen anders sind.
Lwan versucht, während des gesamten Projekts einen konsistenten Codierungsstil zu verfolgen. Wenn Sie in Betracht ziehen, einen Patch zum Projekt beizutragen, respektieren Sie diesen Stil bitte, indem Sie versuchen, den Stil des umgebenden Code zu entsprechen. Im Allgemeinen:
global_variables_are_named_like_this , obwohl sie tendenziell selten sind und als static gekennzeichnet werden sollten (mit seltenen Ausnahmen)local_var , i , conntypedef für Strukturen werden in LWAN selten verwendet#pragma once anstelle des üblichen Wachhackers verwendenlwan-private.h hinzufügen.H.lwan_ vorangestellt werdenlwan_ vorangestellt werdenlwan_ benannt werden/* Old C-style comments are preferred */clang-format can be used to format the source code in an acceptable way; a .clang-format file is provided If modifying well-tested areas of the code (eg the event loop, HTTP parser, etc.), please add a new integration test and make sure that, before you send a pull request, all tests (including the new ones you've sent) are working. Tests can be added by modifying src/scripts/testsuite.py , and executed by either invoking that script directly from the source root, or executing the testsuite build target.
Some tests will only work on Linux, and won't be executed on other platforms.
Lwan is automatically fuzz-tested by OSS-Fuzz. To fuzz-test locally, though, one can follow the instructions to test locally.
Currently, there are fuzzing drivers for the request parsing code, the configuration file parser, the template parser, and the Lua string pattern matching library used in the rewrite module.
Adding new fuzzers is trivial:
src/bin/fuzz .${FUZZER_NAME}_fuzzer.cc . Look at the OSS-Fuzz documentation and other fuzzers on information about how to write these.src/fuzz/corpus . Files have to be named corpus-${FUZZER_NAME}-${UNIQUE_ID} . The shared object version of liblwan on ELF targets (eg Linux) will use a symbol filter script to hide symbols that are considered private to the library. Please edit src/lib/liblwan.sym to add new symbols that should be exported to liblwan.so .
Lwan tries to maintain a source history that's as flat as possible, devoid of merge commits. This means that pull requests should be rebased on top of the current master before they can be merged; sometimes this can be done automatically by the GitHub interface, sometimes they need some manual work to fix conflicts. It is appreciated if the contributor fixes these conflicts when asked.
It is advisable to push your changes to your fork on a branch-per-pull request, rather than pushing to the master branch; the reason is explained below.
Please ensure that Git is configured properly with your name (it doesn't really matter if it is your legal name or a nickname, but it should be enough to credit you) and a valid email address. There's no need to add Signed-off-by lines, even though it's fine to send commits with them.
If a change is requested in a pull request, you have two choices:
It is not enforced, but it is recommended to create smaller commits. How commits are split in Lwan is pretty much arbitrary, so please take a look at the commit history to get an idea on how the division should be made. Git offers a plethora of commands to achieve this result: the already mentioned interactive rebase, the -p option to git add , and git commit --amend are good examples.
Commit messages should have one line of summary (~72 chars), followed by an empty line, followed by paragraphs of 80-char lines explaining the change. The paragraphs explaining the changes are usually not necessary if the summary is good enough. Try to write good commit messages.
Lwan is licensed under the GNU General Public License, version 2, or (at your option), any later version. Daher:
While Lwan was written originally for Linux, it has been ported to BSD systems as well. The build system will detect the supported features and build support library functions as appropriate.
For instance, epoll has been implemented on top of kqueue, and Linux-only syscalls and GNU extensions have been implemented for the supported systems. This blog post explains the details and how #include_next is used.
It can achieve good performance, yielding about 320000 requests/second on a Core i7 laptop for requests without disk access, and without pipelining.
When disk I/O is required, for files up to 16KiB, it yields about 290000 requests/second ; for larger files, this drops to 185000 requests/second , which isn't too shabby either.
These results, of course, with keep-alive connections, and with weighttp running on the same machine (and thus using resources that could be used for the webserver itself).
Without keep-alive, these numbers drop around 6-fold.
There is an IRC channel ( #lwan ) on Libera. A standard IRC client can be used.
Here's a non-definitive list of third-party stuff that uses Lwan and have been seen in the wild. If you see mentions of Lwan in the media or academia, however small it might be, please contact the author! It'll make her day!
Some other distribution channels were made available as well:
Dockerfile is maintained by @jaxgeller, and is available from the Docker registry.Lwan has been also used as a benchmark:
Mentions in academic journals:
Mentions in magazines:
Mentions in books:
Some talks mentioning Lwan:
Not really third-party, but alas:
Lwan container images are available at ghcr.io/lpereira/lwan. Container runtimes like Docker or Podman may be used to build and run Lwan in a container.
Container images are tagged with release version numbers, so a specific version of Lwan can be pulled.
# latest version
docker pull ghcr.io/lpereira/lwan:latest
# pull a specific version
docker pull ghcr.io/lpereira/lwan:v0.3
Clone the repository and use Containerfile (Dockerfile) to build Lwan with all optional dependencies enabled.
podman build -t lwan .
The image expects to find static content at /wwwroot , so a volume containing your content can be mounted.
docker run --rm -p 8080:8080 -v ./www:/wwwroot lwan
To bring your own lwan.conf , simply mount it at /lwan.conf .
podman run --rm -p 8080:8080 -v ./lwan.conf:/lwan.conf lwan
Podman supports socket activation of containers. This example shows how to run lwan with socket activation and Podman on a Linux host.
Requirements: Podman version 4.5.0 or higher.
sudo useradd test
sudo machinectl shell test@
podman build -t lwan ~/lwan
mkdir -p ~/.config/containers/systemd
mkdir -p ~/.config/systemd/user
listener systemd:my.socket
site {
serve_files / {
path = /web
}
}
[Socket]
ListenStream=8080
[Unit]
After=my.socket
Requires=my.socket
[Container]
Network=none
Image=localhost/lwan
Volume=/home/test/lwan.conf:/lwan.conf:Z
Volume=/home/test/web:/web:Z
:Z is needed on SELinux systems. As lwan only needs to communicate over the socket-activated socket, it's possible to use Network=none . See the article How to limit container privilege with socket activation. mkdir ~/web
echo hello > ~/web/file.txt
systemctl --user daemon-reload
systemctl --user start my.socket
$ curl localhost:8080/file.txt
hello
These are some of the quotes found in the wild about Lwan. They're presented in no particular order. Contributions are appreciated:
"Lwan is like a classic, according to the definition given by Italian -- writer Italo Calvino: you can read it again and again" Antonio Piccolboni
"I read lwan's source code. Especially, the part of using coroutine was very impressive and it was more interesting than a good novel. Thank you for that." -- @patagonia
"For the server side, we're using Lwan, which can handle 100k+ reqs/s. It's supposed to be super robust and it's working well for us." -- @fawadkhaliq
"Insane C thing" -- Michael Sproul
"The best performer is LWAN, a newcomer" -- InfoQ
"I've never had a chance to thank you for Lwan. It inspired me a lot to develop Zewo" -- @paulofariarl
"Let me say that lwan is a thing of beauty. I got sucked into reading the source code for pure entertainment, it's so good. high five " -- @kwilczynski
"mad science" -- jwz
"Nice work with Lwan! I haven't looked that carefully yet but so far I like what I saw. You definitely have the right ideas." -- @thinkingfish
"Lwan is a work of art. Every time I read through it, I am almost always awe-struck." -- @neurodrone
"For Round 10, Lwan has taken the crown" -- TechEmpower
"Jeez this is amazing. Just end to end, rock solid engineering. (...) But that sells this work short." kjeetgill
"I am only a spare time C coder myself and was surprised that I can follow the code. Nice!" cntlzw
"Impressive all and all, even more for being written in (grokkable!) C. Nice work." tpaschalis
"LWAN was a complete failure" dermetfan