@@ -3,22 +3,19 @@ module Http
4 , getManager
4 , getManager
10− , Timeout(..)
10+ , Error(..)
11− , Body(..)
11+ -- archives
18 , shaToChars
13 , shaToChars
19− , readArchive
14+ , fetchArchive
20− , writeArchive
15+ -- upload
21− , Error(..)
16+ , upload
@@ -37,7 +34,6 @@ import Network.HTTP.Client.TLS (tlsManagerSettings)
37import Network.HTTP.Types.Header (Header, hAccept, hAcceptEncoding, hUserAgent)
34import Network.HTTP.Types.Header (Header, hAccept, hAcceptEncoding, hUserAgent)
38import Network.HTTP.Types.Method (methodPost)
35import Network.HTTP.Types.Method (methodPost)
39import qualified Network.HTTP.Client.MultipartFormData as Multi
36import qualified Network.HTTP.Client.MultipartFormData as Multi
40−import qualified System.Directory as Dir
42import qualified Elm.Version as V
38import qualified Elm.Version as V
@@ -66,13 +62,7 @@ toUrl url params =
74− -> (BS.ByteString -> IO (Either e a))
65+post :: Manager -> String -> [Header] -> (Error -> e) -> (BS.ByteString -> IO (Either e a)) -> IO (Either e a)
76post manager url headers onError onSuccess =
66post manager url headers onError onSuccess =
77 handle (handleSomeException url onError) $
67 handle (handleSomeException url onError) $
78 handle (handleHttpException url onError) $
68 handle (handleHttpException url onError) $
@@ -87,33 +77,6 @@ post manager url headers onError onSuccess =
87 onSuccess (BS.concat chunks)
77 onSuccess (BS.concat chunks)
97− -> (BodyReader -> IO (Either e a))
99−post' manager url headers timeout body onError onSuccess =
100− handle (handleSomeException url onError) $
101− handle (handleHttpException url onError) $
102− do req0 <- parseUrlThrow url
105− addTimeout timeout $
107− { method = methodPost
108− , requestHeaders = addDefaultHeaders headers
110− withResponse req1 manager (onSuccess . responseBody)
117addDefaultHeaders :: [Header] -> [Header]
80addDefaultHeaders :: [Header] -> [Header]
118addDefaultHeaders headers =
81addDefaultHeaders headers =
119 (hUserAgent, userAgent) : (hAcceptEncoding, "gzip") : headers
82 (hUserAgent, userAgent) : (hAcceptEncoding, "gzip") : headers
@@ -131,54 +94,6 @@ accept mime =
142−addTimeout :: Timeout -> Request -> Request
143−addTimeout timeout req =
149− req { responseTimeout = responseTimeoutNone }
158− | FormDataBody [Multi.Part]
161−addBody :: Body -> Request -> IO Request
167− FormDataBody parts ->
168− Multi.formDataBody parts req
171−filePart :: String -> FilePath -> Multi.Part
172−filePart name filePath =
173− Multi.partFileSource (String.fromString name) filePath
176−stringPart :: String -> String -> Multi.Part
177−stringPart name string =
178− Multi.partBS (String.fromString name) (BS.pack string)
182-- EXCEPTIONS
97-- EXCEPTIONS
@@ -204,12 +119,7 @@ handleSomeException url onError exception =
207−-- BODY READERS
122+-- SHA
210−readByteString :: BodyReader -> IO BS.ByteString
211−readByteString bodyReader =
212− BS.concat <$> brConsume bodyReader
215type Sha = SHA.Digest SHA.SHA1State
125type Sha = SHA.Digest SHA.SHA1State
@@ -220,6 +130,33 @@ shaToChars =
220 SHA.showDigest
130 SHA.showDigest
142+ -> ((Sha, Zip.Archive) -> IO (Either e a))
144+fetchArchive manager url onError err onSuccess =
145+ handle (handleSomeException url onError) $
146+ handle (handleHttpException url onError) $
147+ do req0 <- parseUrlThrow url
150+ { method = methodPost
151+ , requestHeaders = addDefaultHeaders []
153+ withResponse req1 manager $ \response ->
154+ do result <- readArchive (responseBody response)
156+ Nothing -> return (Left err)
157+ Just shaAndArchive -> onSuccess shaAndArchive
223readArchive :: BodyReader -> IO (Maybe (Sha, Zip.Archive))
160readArchive :: BodyReader -> IO (Maybe (Sha, Zip.Archive))
224readArchive body =
161readArchive body =
225 readArchiveHelp body $
162 readArchiveHelp body $
@@ -254,20 +191,30 @@ readArchiveHelp body (AS len sha zip) =
257−-- WRITE ARCHIVE
194+-- UPLOAD
260−writeArchive :: Zip.Archive -> FilePath -> FilePath -> IO ()
197+upload :: Manager -> String -> [Multi.Part] -> IO (Either Error ())
261−writeArchive archive destination newRoot =
198+upload manager url parts =
262− do Dir.createDirectoryIfMissing True destination
199+ handle (handleSomeException url id) $
263− let opts = [Zip.OptDestination destination]
200+ handle (handleHttpException url id) $
264− mapM_ (Zip.writeEntry opts . replaceRoot newRoot) (Zip.zEntries archive)
201+ do req0 <- parseUrlThrow url
203+ Multi.formDataBody parts $
205+ { method = methodPost
206+ , requestHeaders = addDefaultHeaders []
207+ , responseTimeout = responseTimeoutNone
209+ withResponse req1 manager $ \_ ->
213+filePart :: String -> FilePath -> Multi.Part
214+filePart name filePath =
215+ Multi.partFileSource (String.fromString name) filePath
267−replaceRoot :: String -> Zip.Entry -> Zip.Entry
218+stringPart :: String -> String -> Multi.Part
268−replaceRoot root entry =
219+stringPart name string =
269− let
220+ Multi.partBS (String.fromString name) (BS.pack string)
271− dropWhile (/='/') (Zip.eRelativePath entry)
273− entry { Zip.eRelativePath = root ++ rootless }