[web-devel] proxy with wai

Jos van den Oever jos at vandenoever.info
Thu Mar 26 19:10:24 UTC 2015


On Tuesday 24 March 2015 07:01:39 Michael Snoyman wrote:
> On Sun, Mar 22, 2015 at 10:01 AM Jos van den Oever <jos at vandenoever.info>
> 
> wrote:
> > On Sunday 08 March 2015 07:28:30 you wrote:
> > > I've updated that Gist to be compatible with WAI 3.0. The basic changes
> > > I
> > > made were:
> > > 
> > > 1. Change the way Warp settings are applied (no longer use record
> > > syntax,
> > > but explicit set* functions).
> > > 2. conduit is no longer the standard streaming interface for WAI, so
> > > imported Network.Wai.Conduit and used helper functions from there.
> > > 3. The specific question you asked about: the semantics for how to do
> > > resource allocation in an application have changed. There were some
> > > holes
> > > in the previous approach that allowed async exceptions to leak in at the
> > > wrong time. Instead, WAI 3.0 uses a similar interface to most resource
> > > allocation functions in Haskell (like bracket or withFile).
> > > Specifically,
> > > 
> > > this looks like:
> > >     HCl.withResponse req2 man $ \res -> do
> > >     
> > >         let body = mapOutput (Chunk . fromByteString) $
> > > 
> > > HCC.bodyReaderSource $ HCl.responseBody res
> > > 
> > >             headers = filter safeResHeader $ HCl.responseHeaders res
> > >         
> > >         respond $ responseSource (HCl.responseStatus res) headers body
> > 
> > I'd like my proxy to be a caching proxy so each request shoule be saved to
> > a
> > file. I've tried adding an additional sink, (sinkFile) or conduit
> > (conduitFie)
> > to the HCC.bodyReaderSource, but cannot it right. What would be a good way
> > to
> > do this?
> 
> What have you tried so far?

This is the code I have so far. I've annotated with a types. This code gives a 
compile error because of the line 'source2 = bodySource C.=$= fileSaver'. The 
MonadResource is not arising from the use in fileSaver. Somehow, I've to get 
runResourceT in there.

===
    HCl.withResponse req2 man $ \res -> do
        --saver <- CB.conduitFile "/tmp/out"

        let path = "/tmp/out" :: FilePath
            fileSaver :: MonadResource m => C.Conduit S8.ByteString m 
S8.ByteString
            fileSaver = CB.conduitFile path
            bodyReader :: HCl.BodyReader
            bodyReader = HCl.responseBody res
            bodySource :: MonadIO m => C.ConduitM () S8.ByteString m ()
            bodySource = HCC.bodyReaderSource bodyReader
            source2 = bodySource C.=$= fileSaver
            chunk :: S8.ByteString -> C.Flush Builder
            chunk = C.Chunk . fromByteString
            body :: C.ConduitM () (C.Flush Builder) IO()
            body = C.mapOutput chunk source2
            headers = filter removeEncodingHeaders $ HCl.responseHeaders res

        time <- getPOSIXTime
        runSqlPool (insert_ $ Response (round time) reqid Nothing) pool
        respond $ WC.responseSource (HCl.responseStatus res) headers body
===

Cheers,
Jos





More information about the web-devel mailing list