Ich habe neugierig auf WAI
interface geschaut und während es einfach aussieht, war ich überrascht zu sehen, wie viele Iterationen es brauchte, um sich bei der aktuellen Form zu stabilisieren!
Ich hatte angenommen, dass der CPS-Stil für die Ressourcensicherheit die interessanteste Sache wäre, aber es sieht so aus, als gäbe es noch viel mehr zu lernen!
%Vor%Einige Archäologie liefert etwas unbefriedigende Ergebnisse:
%Vor%Alle Designs scheinen von drei Hauptanliegen getrieben zu sein:
Diese Version verwendet iterates, was war eine frühe Lösung für das Streaming von Daten in Haskell. Iteratee-Konsumenten mussten auf "Push-basierte" Weise geschrieben werden, was wohl weniger natürlich war als die "Pull-basierten" Konsumenten, die in modernen Streaming-Bibliotheken verwendet werden.
Der gestreamte Körper der Anfrage wird dem iteratee zugeführt und wir erhalten einen Response
-Wert am Ende. Das Response
enthält einen Enumerator (eine Funktion, die gestreamte Antwortbytes an einen Antwort-iteratee liefert, der vom Server bereitgestellt wird). Vermutlich würde der Enumerator die Ressourcenzuweisung mit Funktionen wie bracket
steuern.
Diese Version verwendet resourcet Monad-Transformer für die Ressourcenverwaltung, anstatt es im Enumerator zu tun. Es gibt einen speziellen Source
Typ sowohl in Request
als auch in Response
, der gestreamte Daten verarbeitet (und was IMHO etwas schwer zu verstehen ist).
Diese Version verwendet die Streaming-Abstraktionen aus dem Conduit , vermeidet jedoch resource und bietet stattdessen eine Klammer wie responseSourceBracket
Funktion zum Umgang mit Ressourcen in gestreamten Antworten.
Diese Version wechselt zu einem fortsetzungsbasierten Ansatz, der es ermöglicht Die Handler-Funktion verwendet reguläre bracket
-ähnliche Funktionen, um die Ressourcenzuweisung zu steuern. Zurück zum Anfang, in dieser Hinsicht!
Conduits werden nicht mehr zum Streaming verwendet. Jetzt gibt es eine einfache Request -> IO ByteString
Funktion für Lesen von Brocken des Anfragekörpers und einer (Builder -> IO ()) -> IO () -> IO ()
Funktion in Response
zum Generieren des Antwort-Streams. (Die Funktion Builder -> IO ()
write wird zusammen mit einer Flush-Aktion vom Server bereitgestellt.)
Wie bei den ressourcenbasierten Versionen und im Gegensatz zur iteratebasierten Version können Sie sich bei dieser Implementierung überlappen, indem Sie den Anfragetext mit dem Streamen der Antwort lesen.
Der polymorphe Handler ist ein netter Trick, um sicherzustellen, dass der Response-Callback Response -> IO b
immer aufgerufen wird: Der Handler muss b
zurückgeben, und die einzige Möglichkeit, einen zu erhalten, besteht darin, den Callback aufzurufen!
Diese polymorphe Lösung scheint einige Probleme verursacht zu haben (vielleicht beim Speichern von Handlern in Containern?) Anstatt Polymorphie zu verwenden, können wir ein ResponseReceived
-Token ohne einen öffentlichen Konstruktor verwenden. Der Effekt ist der gleiche: Die einzige Möglichkeit für Handler-Code, das zurückzugebende Token zu erhalten, besteht darin, den Rückruf aufzurufen.
Tags und Links haskell haskell-wai