[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