2016-01-24 23 views
6

Sto cercando di aggiungere una funzionalità al mio server servant che otterrebbe un file da Amazon S3 e lo ritorni all'utente. Dato che i file possono essere grandi, non voglio scaricarli localmente e quindi servirli ai client, preferisco piuttosto trasmetterli direttamente da S3 ai client.Haskell Servant e streaming

Io uso Amazonka per quello che faccio con S3 e posso ottenere un flusso per un file S3 come un sink Conduit.

Ma ora non so come passare da Sink a EitherT ServantErr IO a.

Qualcuno può spiegarmi come farlo o mostrarmi un esempio di come può essere fatto?

+0

C'è attualmente un PR in Servant per aggiungere "Supporto endpoint Stream". https://github.com/haskell-servant/servant/pull/836 – erewok

risposta

4

Non c'è niente in Servant per fare questo fuori dalla scatola, tuttavia sono disponibili tutte le parti necessarie.

Prima di iniziare, credo che se è possibile lo streaming di un lavandino, che significa avere una fonte (il gorsBody di GetObjectResponse è un RsBody, che è una fonte)

Prima di tutto, Servo ci fornisce con la possibilità di aggiungere il supporto per i nuovi tipi di resi, creando una nuova istanza di HasServer, in modo da poter servire uno EitherT ServantErr IO (Source ...) e farlo flusso.

Per creare tale istanza, è necessario implementare route :: Proxy layout -> Server layout -> RoutingApplication. Server layout, in questo caso, indica semplicemente EitherT ServantErr IO layout, layout come origine del server, quindi è la funzione che restituisce un'origine (e potrebbe non riuscire con un errore HTTP).

dobbiamo restituire un RoutingApplication, che è (in stile proseguimento) una funzione che prende un Request e restituisce un RouteResult Response, il che significa che sia un errore percorso senza pari, o una risposta. Entrambi Request e Response sono standard wai, non Servant, quindi ora possiamo esaminare il resto dell'ecosistema per scoprire come implementarlo.

Fortunatamente, non abbiamo bisogno di andare lontano: Network.Wai.Conduit contiene solo ciò che abbiamo bisogno di implementare la funzione route: responseSource assume un valore di stato, alcune intestazioni di risposta e la vostra sorgente e ti dà una Response.

Quindi, c'è parecchio lavoro da fare, ma tutto ciò di cui abbiamo bisogno è lì. Guardando il numero source of the instance HasServer * (Get ...) potrebbe essere d'aiuto.

+0

Penso che aggiungere una spiegazione/riferimento per come farlo a livello di WAI sarebbe buono per capire come questo si inserisca nel livello di servant. Per me non è chiaro cosa consumi ciò che 'route' ritorna e come pensare alla configurazione dello stile di continuazione qui. – user239558