[web-devel] Upgrading to warp 2
Bardur Arantsson
spam at scientician.net
Tue Feb 25 19:43:15 UTC 2014
On 2014-02-25 05:49, Michael Snoyman wrote:
> On Mon, Feb 24, 2014 at 11:00 PM, Bardur Arantsson <spam at scientician.net>wrote:
(I've taken the liberty of CC'ing the list.)
>
>> Hi all,
>>
[--snip--]
>> When I try this I get:
>>
>> src/Handlers.hs:96:54:
>> No instance for (MonadResource IO)
>> arising from a use of `sourceFileRange'
>> Possible fix: add an instance declaration for (MonadResource IO)
>> In the second argument of `($)', namely
>> `sourceFileRange sfp (Just l') (Just n)'
>> In the expression:
>> mapOutput (Chunk . fromByteString)
>> $ sourceFileRange sfp (Just l') (Just n)
>> In an equation for `src':
>> src
>> = mapOutput (Chunk . fromByteString)
>> $ sourceFileRange sfp (Just l') (Just n)
>>
>> ... which I guess kinda makes sense -- you'd need a ResourceT (or
>> similar) in the monad stack. I'm just not sure how or where to introduce
>> the ResourceT to get this working.
>>
>> If I introduce an explicit type signature for "src",
>>
>> src :: forall m . MonadResource m => Source m (Flush Builder)
>>
>> then that line compiles, but I get the equivalent error at the usage
>> site of "src" in the third argument to "responseSource" (which again
>> also makes sense).
>>
>> Anyone got any pointers?
>>
>> Regards,
>>
>>
> Firstly, why aren't you just using responseFile[1]? That will be more
> efficient than using a Source directly, since Warp is able to use the
> sendfile system call, not to mention all of Kazu's fancy fd-caching logic.
> Even on a non-Warp backend, the functionality can simply degrade to being
> the same as using a Source. Also, not sure if it's relevant, but Warp can
> automatically handle range requests for you, so if you simply return a
> responseFile and the user requests part of the file, Warp will
> automatically generate the 206 response.
>
ResponseFile is broken for some clients (with Linux host at least),
specifically my type of client, a PlayStation 3 (UPnP media player).
There was a Thread of Doom(TM) about it on haskell-cafe, but it caused
FD leaks, though we never found out quite *why* it was broken that way.
(Things may have changed since this was in February 2010, but frankly I
don't even care to spend the time to find out -- I don't need the
performance anyway. I think I remember testing the WAI/Warp sendfile
equivalent in pre-2.0 WAI/Warp and finding that it still had the same
problem.)
> Anyway, the issue here is that in WAI 2.0, we removed ResourceT from the
> WAI stack for efficiency reasons.
Yup, I noticed that ;)
> That makes the cases where you *do* need
> to safely allocate scarce resources like a file handle a bit trickier. In
> this case, I wouldn't bother with ResourceT at all, but instead explicitly
> use the bracket pattern, via responseSourceBracket, openFile, and
> closeFile. This would look like:
>
> serveFile :: Integer -> [(Maybe Integer, Maybe Integer)] -> IO Response
> serveFile fsz [(l,h)] = do
> let l' = maybe 0 id l
> let h' = maybe (fsz-1) id h
> let n = (h' - l' + 1)
> let src h = mapOutput (Chunk . fromByteString) $ sourceHandleRange h
> (Just l') (Just n)
> sfp = "foo.hs"
> responseSourceBracket
> (IO.openFile sfp IO.ReadMode) (IO.hClose) $ \h ->
> return (partialContent206, [], src h)
>
>
> [1]
> http://hackage.haskell.org/package/wai-2.0.0/docs/Network-Wai.html#v:responseFile
>
Ah, yes, this works! I had noticed responseSourceBracket, but (stupidly)
didn't actually try it. Thank you very much.
Regards,
More information about the web-devel
mailing list