Your message dated Wed, 06 Aug 2014 21:52:30 +0000
with message-id <[email protected]>
and subject line Bug#757272: fixed in haskell-dav 0.8-1
has caused the Debian Bug report #757272,
regarding getContentM and putContentM do not support large files
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact [email protected]
immediately.)


-- 
757272: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=757272
Debian Bug Tracking System
Contact [email protected] with problems
--- Begin Message ---
Package: hdav
Version: 0.6.2-1+b5
Tags: patch
Severity: normal

The current getContentM and putContentM interfaces buffer the whole file
content in memory.

However, http-client provides interfaces that can be used to avoid this
problem.

For putContentM, the problem is that, while a lazy bytestring is
provided to RequestBodyLBS, http-client needs to know the length of its
request body. So it buffers the whole thing to calculate its length.
(http-client's documentation could be more clear about this..)

Fixing putContentM is as simple as exposing an interface that lets the
caller provide a RequestBody. Then they can provide eg, a RequestBodyStream
streaming in the content of a file in constant memory.

For getContentM, things are tricker, because davRequest calls httpLbs,
which buffers the whole response body. So, the Request generation needs
to be factored out, and then davRequest can be left as-is, while
providing a withContentM that uses Network.HTTP.Client.withResponse.
The caller can then stream the response (eg out to a file) in constant memory.

git patch attached.

-- 
see shy jo
From 550b24904a8ad3e83c42aff4d1a8af9f392955fb Mon Sep 17 00:00:00 2001
From: Joey Hess <[email protected]>
Date: Wed, 6 Aug 2014 15:35:14 -0400
Subject: [PATCH] add support for large files

The current getContentM and putContentM interfaces buffer the whole file
content in memory.

However, http-client provides interfaces that can be used to avoid this
problem.

For putContentM, the problem is that, while a lazy bytestring is
provided to RequestBodyLBS, http-client needs to know the length of its
request body. So it buffers the whole thing to calculate its length.
(http-client's documentation could be more clear about this..)

Fixing putContentM is as simple as exposing an interface that lets the
caller provide a RequestBody. Then they can provide eg, a RequestBodyStream
streaming in the content of a file in constant memory.

For getContentM, things are tricker, because davRequest calls httpLbs,
which buffers the whole response body. So, the Request generation needs
to be factored out, and then davRequest can be left as-is, while
providing a withContentM that uses Network.HTTP.Client.withResponse.
The caller can then stream the response (eg out to a file) in constant
memory.
---
 Network/Protocol/HTTP/DAV.hs | 36 ++++++++++++++++++++++++++++++------
 1 file changed, 30 insertions(+), 6 deletions(-)

diff --git a/Network/Protocol/HTTP/DAV.hs b/Network/Protocol/HTTP/DAV.hs
index 94d21bc..c8d76ea 100644
--- a/Network/Protocol/HTTP/DAV.hs
+++ b/Network/Protocol/HTTP/DAV.hs
@@ -41,10 +41,12 @@ module Network.Protocol.HTTP.DAV (
   , delContentM
   , getPropsM
   , getContentM
+  , withContentM
   , mkCol
   , moveContentM
   , putPropsM
   , putContentM
+  , putContentM'
   , withLockIfPossible
   , withLockIfPossibleForDelete
   , module Network.Protocol.HTTP.DAV.TH
@@ -72,7 +74,7 @@ import qualified Data.Map as Map
 
 import Data.Maybe (catMaybes, fromMaybe)
 
-import Network.HTTP.Client (RequestBody(..), httpLbs, parseUrl, applyBasicAuth, Request(..), Response(..), newManager, closeManager, HttpException(..))
+import Network.HTTP.Client (RequestBody(..), httpLbs, parseUrl, applyBasicAuth, Request(..), Response(..), newManager, closeManager, HttpException(..), BodyReader, withResponse)
 import Network.HTTP.Client.TLS (tlsManagerSettings)
 import Network.HTTP.Types (hContentType, Method, Status, RequestHeaders, unauthorized401, conflict409)
 
@@ -120,8 +122,8 @@ setUserAgent ua = userAgent .= ua
 setResponseTimeout :: MonadIO m => Maybe Int -> DAVT m ()
 setResponseTimeout rt = baseRequest %= \x -> x { responseTimeout = rt }
 
-davRequest :: MonadIO m => Method -> RequestHeaders -> RequestBody -> DAVT m (Response BL.ByteString)
-davRequest meth addlhdrs rbody = do
+mkDavRequest :: MonadIO m => Method -> RequestHeaders -> RequestBody -> DAVT m Request
+mkDavRequest meth addlhdrs rbody = do
     ctx <- get
     let hdrs = catMaybes
                [ Just (mk "User-Agent", ctx ^. userAgent)
@@ -131,7 +133,14 @@ davRequest meth addlhdrs rbody = do
         authreq = if B.null (ctx ^. basicusername) && B.null (ctx ^. basicpassword)
             then req
             else applyBasicAuth (ctx ^. basicusername) (ctx ^. basicpassword) req
-    liftIO (httpLbs authreq (ctx ^. httpManager))
+    return authreq
+
+davRequest :: MonadIO m => Method -> RequestHeaders -> RequestBody -> DAVT m (Response BL.ByteString)
+davRequest meth addlhdrs rbody = go =<< mkDavRequest meth addlhdrs rbody
+  where
+    go req = do
+      ctx <- get
+      liftIO (httpLbs req (ctx ^. httpManager))
 
 matchStatusCodeException :: Status -> HttpException -> Maybe ()
 matchStatusCodeException want (StatusCodeException s _ _)
@@ -182,18 +191,33 @@ getPropsM = do
     propresp <- davRequest "PROPFIND" ahs (xmlBody propname)
     return $ (XML.parseLBS_ XML.def . responseBody) propresp
 
+-- | Note that the entire request body is buffered in memory.
+-- To stream large files use withContentM instead.
 getContentM :: MonadIO m => DAVT m (Maybe B.ByteString, BL.ByteString)
 getContentM = do
     resp <- davRequest "GET" [] emptyBody
     let ct = lookup hContentType (responseHeaders resp)
     return (ct, responseBody resp)
 
+withContentM :: MonadIO m => (Response BodyReader -> IO a) -> DAVT m a
+withContentM handleresponse = do
+    req <- mkDavRequest "GET" [] emptyBody
+    ctx <- get
+    liftIO $ withResponse req (ctx ^. httpManager) handleresponse
+
+-- | Note that the entire request body is buffered in memory; not suitable
+-- for large files.
 putContentM :: MonadIO m => (Maybe B.ByteString, BL.ByteString) -> DAVT m ()
-putContentM (ct, body) = do
+putContentM (ct, body) = putContentM' (ct, RequestBodyLBS body)
+
+-- | To send a large file, pass eg a RequestBodyStream containing the
+-- file's content.
+putContentM' :: MonadIO m => (Maybe B.ByteString, RequestBody) -> DAVT m ()
+putContentM' (ct, requestbody) = do
     d <- get
     let ahs' = maybe [] (return . (,) (mk "If") . parenthesize) (d ^. lockToken)
     let ahs = ahs' ++ maybe [] (return . (,) hContentType) ct
-    _ <- davRequest "PUT" ahs (RequestBodyLBS body)
+    _ <- davRequest "PUT" ahs requestbody
     return ()
 
 delContentM :: MonadIO m => DAVT m ()
-- 
2.0.1

Attachment: signature.asc
Description: Digital signature


--- End Message ---
--- Begin Message ---
Source: haskell-dav
Source-Version: 0.8-1

We believe that the bug you reported is fixed in the latest version of
haskell-dav, which is due to be installed in the Debian FTP archive.

A summary of the changes between this version and the previous one is
attached.

Thank you for reporting the bug, which will now be closed.  If you
have further comments please address them to [email protected],
and the maintainer will reopen the bug report if appropriate.

Debian distribution maintenance software
pp.
Clint Adams <[email protected]> (supplier of updated haskell-dav package)

(This message was generated automatically at their request; if you
believe that there is a problem with it please contact the archive
administrators by mailing [email protected])


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

Format: 1.8
Date: Wed, 06 Aug 2014 17:09:56 -0400
Source: haskell-dav
Binary: hdav libghc-dav-dev libghc-dav-prof libghc-dav-doc
Architecture: source all amd64
Version: 0.8-1
Distribution: unstable
Urgency: medium
Maintainer: Debian Haskell Group 
<[email protected]>
Changed-By: Clint Adams <[email protected]>
Description:
 hdav       - command-line WebDAV client
 libghc-dav-dev - RFC 4918 WebDAV support
 libghc-dav-doc - RFC 4918 WebDAV support; documentation
 libghc-dav-prof - RFC 4918 WebDAV support; profiling libraries
Closes: 757272
Changes:
 haskell-dav (0.8-1) unstable; urgency=medium
 .
   * New upstream version.
     - includes "large file" support by Joey Hess.  closes: #757272.
Checksums-Sha1:
 434ac44c28784747ce4cea6de7df482781446073 3667 haskell-dav_0.8-1.dsc
 285f71c54aecec78c683820da7e2e015491d65b3 19976 haskell-dav_0.8.orig.tar.gz
 ede1cbb8a5c7cc76c180b1928d5dd01e27215bd1 2324 haskell-dav_0.8-1.debian.tar.xz
 acea3d02d1a5db838773caf13b596587561e131a 41976 libghc-dav-doc_0.8-1_all.deb
 04643fc30186d8acbaf00620c075a27b821b23f8 1771688 hdav_0.8-1_amd64.deb
 03e16ba1578df6ddb2662f237dde547a30bc38d1 110846 libghc-dav-dev_0.8-1_amd64.deb
 f87ff53fc58690e2312eebe9abb7b4ff567669a8 130852 libghc-dav-prof_0.8-1_amd64.deb
Checksums-Sha256:
 8ee779dfe52c8962618160a335f8e5e1bc24915a0c1d70f72be3bccc2acee946 3667 
haskell-dav_0.8-1.dsc
 1901a62748916d37413b7cacf1eec97845e2158277b164fb60c429254b8b124e 19976 
haskell-dav_0.8.orig.tar.gz
 c46093cf03da0a793fb75f9a9a8ef334c4d6df41aebad134d4cbb22b9e54a547 2324 
haskell-dav_0.8-1.debian.tar.xz
 e34ff0e66ee191c55b63537b5010e65699cc3ae414f6332a87cd84e908c36999 41976 
libghc-dav-doc_0.8-1_all.deb
 a928ec202f772a957ed698a6310feb761c4122b90403c9457f05235fc0c4cbfc 1771688 
hdav_0.8-1_amd64.deb
 31e475cae842ddfa7024dcf7ef742d44a400e80c0a26c874851a807ea4919e9a 110846 
libghc-dav-dev_0.8-1_amd64.deb
 d0572f77370667258771dfd7176042cc1368bd255997841b5352cf7a11a546e4 130852 
libghc-dav-prof_0.8-1_amd64.deb
Files:
 5c8019a6945d24f96a175725284f758a 41976 doc extra libghc-dav-doc_0.8-1_all.deb
 41b216d09d884366080b0c54f318fdc3 1771688 web extra hdav_0.8-1_amd64.deb
 0e60b6ea21b6cd786615252be9d00be7 110846 haskell extra 
libghc-dav-dev_0.8-1_amd64.deb
 e17cc24c7dd1e34ceb2ecf446251fe9b 130852 haskell extra 
libghc-dav-prof_0.8-1_amd64.deb
 313c5b7d1fd809d7ee200545701345f9 3667 haskell extra haskell-dav_0.8-1.dsc
 b71ae271abf339f45bff67bcee424250 19976 haskell extra 
haskell-dav_0.8.orig.tar.gz
 6c485079e2f22704e1c2e07eba904bf1 2324 haskell extra 
haskell-dav_0.8-1.debian.tar.xz

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2
Comment: Debian!

iQJ8BAEBCgBmBQJT4p4IXxSAAAAAAC4AKGlzc3Vlci1mcHJAbm90YXRpb25zLm9w
ZW5wZ3AuZmlmdGhob3JzZW1hbi5uZXQ3NTgxRUM4NzQwNTNFNkM4MDc3OTFCOUI1
NTkyMzMxRTE5OUQzOEE4AAoJEFWSMx4ZnTioetcP/2HmltOa+4nUngECslkzBAgm
ZDrHH72eVW+EEiRu0p2Z0BBDkZpGi/33gQ3dbwMh6sQcbhkdiDCuI/4fDGem8TNb
+ffmtyDKMuuNSEfzH3hsJ9Z2yT6jsfc5tS6nW4UekP+eK9QFnoAUjht0yGbjtt2r
bLFMt/VnJUT7HpQTtjBXPP6/i4jkbgK90SgXZ8GK6Or6nedw0XMyZ6xgpDXlt0dH
pbpM5RBJqEHJDh28XgivGR81vLnMHKl9ShBka5cUuTmPwsJr5DiuzvHQxj237kax
/XYrbDBL83fPkim8xwIHJafspZT7fuYjXb96szRSA39wal9hj6X/a3ZegCN/l3xp
eiLHNRXqnTdTi+dkpziABrBIzZX3/MLKXwijgzfRYZM2hxcPjVI7E4qd9QyFNiCR
r4e/D/4NqUlY18A+MaCEmjVoZub7+ogFzQJCpluoq7u60cY7wMJCSdDc6K4RP05B
m6XV3d94W+7ds/cwqNhQi9JxmfJBJpLXbkZfH6dwo4tYzMm5QBnRDGtQDihv7oxZ
XS70JEJ5e0aQn94iu0bDCxnfc/vgrp/Cb9RBztFZm9PcoDiM9d8sXY58Aic/l4YI
U1jghb8qWMeWqdxVYM0qoUXK9UwESKlrXXUCm+B8IxmH3TwbCdJb60eWLrY6Kf1x
T6NByBGYlLXx5pe4Uej2
=A/X5
-----END PGP SIGNATURE-----

--- End Message ---

Reply via email to