@@ -39,6 +39,15 @@ module Network.HTTP.StackClient
3939 , partFileRequestBody
4040 , partBS
4141 , partLBS
42+ , setGithubHeaders
43+ , download
44+ , redownload
45+ , verifiedDownload
46+ , CheckHexDigest (.. )
47+ , DownloadRequest (.. )
48+ , drRetryPolicyDefault
49+ , DownloadException (.. )
50+ , HashCheck (.. )
4251 ) where
4352
4453import Data.Aeson (FromJSON )
@@ -50,9 +59,13 @@ import Network.HTTP.Simple (setRequestMethod, setRequestBody, setReque
5059import Network.HTTP.Types (hAccept , hContentLength , hContentMD5 , methodPut )
5160import Network.HTTP.Conduit (requestHeaders )
5261import Network.HTTP.Client.TLS (getGlobalManager , applyDigestAuth , displayDigestAuthException )
62+ import Network.HTTP.Download hiding (download , redownload , verifiedDownload )
63+ import qualified Network.HTTP.Download as Download
5364import qualified Network.HTTP.Simple
5465import Network.HTTP.Client.MultipartFormData (formDataBody , partFileRequestBody , partBS , partLBS )
66+ import Path
5567import RIO
68+ import RIO.PrettyPrint
5669
5770
5871setUserAgent :: Request -> Request
@@ -83,3 +96,52 @@ withResponse
8396 :: (MonadUnliftIO m , MonadIO n )
8497 => Request -> (Response (ConduitM i Strict. ByteString n () ) -> m a ) -> m a
8598withResponse = Network.HTTP.Simple. withResponse . setUserAgent
99+
100+ -- | Set the user-agent request header
101+ setGithubHeaders :: Request -> Request
102+ setGithubHeaders = setRequestHeader " Accept" [" application/vnd.github.v3+json" ]
103+
104+ -- | Download the given URL to the given location. If the file already exists,
105+ -- no download is performed. Otherwise, creates the parent directory, downloads
106+ -- to a temporary file, and on file download completion moves to the
107+ -- appropriate destination.
108+ --
109+ -- Throws an exception if things go wrong
110+ download :: HasTerm env
111+ => Request
112+ -> Path Abs File -- ^ destination
113+ -> RIO env Bool -- ^ Was a downloaded performed (True) or did the file already exist (False)?
114+ download req dest = Download. download (setUserAgent req) dest
115+
116+ -- | Same as 'download', but will download a file a second time if it is already present.
117+ --
118+ -- Returns 'True' if the file was downloaded, 'False' otherwise
119+ redownload :: HasTerm env
120+ => Request
121+ -> Path Abs File -- ^ destination
122+ -> RIO env Bool
123+ redownload req dest = Download. redownload (setUserAgent req) dest
124+
125+ -- | Copied and extended version of Network.HTTP.Download.download.
126+ --
127+ -- Has the following additional features:
128+ -- * Verifies that response content-length header (if present)
129+ -- matches expected length
130+ -- * Limits the download to (close to) the expected # of bytes
131+ -- * Verifies that the expected # bytes were downloaded (not too few)
132+ -- * Verifies md5 if response includes content-md5 header
133+ -- * Verifies the expected hashes
134+ --
135+ -- Throws VerifiedDownloadException.
136+ -- Throws IOExceptions related to file system operations.
137+ -- Throws HttpException.
138+ verifiedDownload
139+ :: HasTerm env
140+ => DownloadRequest
141+ -> Path Abs File -- ^ destination
142+ -> (Maybe Integer -> ConduitM ByteString Void (RIO env ) () ) -- ^ custom hook to observe progress
143+ -> RIO env Bool -- ^ Whether a download was performed
144+ verifiedDownload dr destpath progressSink =
145+ Download. verifiedDownload dr' destpath progressSink
146+ where
147+ dr' = dr {drRequest = setUserAgent (drRequest dr)}
0 commit comments