packages feed

list-t-libcurl (empty) → 0.2.0.0

raw patch · 4 files changed

+194/−0 lines, 4 filesdep +basedep +base-preludedep +bytestringsetup-changed

Dependencies added: base, base-prelude, bytestring, curlhs, either, list-t, mtl-prelude, resource-pool, stm, template-haskell

Files

+ LICENSE view
@@ -0,0 +1,22 @@+Copyright (c) 2015, Nikita Volkov++Permission is hereby granted, free of charge, to any person+obtaining a copy of this software and associated documentation+files (the "Software"), to deal in the Software without+restriction, including without limitation the rights to use,+copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the+Software is furnished to do so, subject to the following+conditions:++The above copyright notice and this permission notice shall be+included in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR+OTHER DEALINGS IN THE SOFTWARE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ library/ListT/Libcurl.hs view
@@ -0,0 +1,109 @@+module ListT.Libcurl+(+  Session,+  Error,+  runSession,+  consumeURL,+)+where++import BasePrelude hiding (cons, uncons)+import Foreign hiding (Pool, void)+import MTLPrelude hiding (Error)+import Control.Monad.Trans.Either hiding (left, right)+import ListT (ListT)+import Data.ByteString (ByteString)+import Control.Concurrent.STM.TMVar+import qualified Data.ByteString as B+import qualified Data.ByteString.Unsafe as BU+import qualified Data.Pool as P+import qualified Network.CURL720 as C+import qualified ListT as L+import qualified Language.Haskell.TH.Syntax as TH+++-- |+-- A global sessions pool.+-- +-- Due to how the \"libcurl\" library integration is handled,+-- there may only exist one per application, +-- hence the API provides no way to establish another pool.+{-# NOINLINE pool #-}+pool :: P.Pool C.CURL+pool =+  unsafePerformIO $ P.createPool acquire release 1 30 100+  where+    acquire = do+      h <- C.curl_easy_init+      C.curl_easy_setopt h [C.CURLOPT_FAILONERROR True]+      return h+    release h = do+      C.curl_easy_cleanup h+++-- |+-- A monad for sequential execution of \"libcurl\" operations.+-- +-- To execute multiple requests concurrently you need to run multiple sessions.+newtype Session a =+  Session (ReaderT C.CURL IO a)+  deriving (Functor, Applicative, Monad, MonadIO)++type Error =+  C.CURLE+++runSession :: Session a -> IO (Either Error a)+runSession (Session m) =+  try $+  C.withlib C.CURL720 $+  P.withResource pool $ +  runReaderT m++consumeURL :: String -> (ListT IO ByteString -> IO a) -> Session a+consumeURL url consumer =+  Session $ ReaderT $ \h -> do+    syncState@(active, chunk) <- atomically $ newSyncState+    C.curl_easy_setopt h+      [+        C.CURLOPT_WRITEFUNCTION $ Just (syncWriteFunction syncState),+        C.CURLOPT_URL url+      ]+    result <- newEmptyMVar :: IO (MVar (Either SomeException a))+    forkIO $ do+      r <- +        try $ consumer $ fix $ \loop -> do+          chunk <- +            lift $ atomically $+              tryTakeTMVar chunk >>= \case+                Just chunk -> return $ Just chunk+                _ -> readTVar active >>= \case+                  False -> return Nothing+                  _ -> retry+          case chunk of+            Nothing -> mzero+            Just chunk -> L.cons chunk loop+      atomically $ writeTVar active False+      putMVar result r+    catch (C.curl_easy_perform h) $ \case+      C.CURLE _ _ _ C.CURLE_WRITE_ERROR -> return ()+      e -> throwIO e+    atomically $ writeTVar active False+    either (throwIO :: SomeException -> IO a) return =<< takeMVar result+++type SyncState =+  (TVar Bool, TMVar ByteString)++newSyncState :: STM SyncState+newSyncState =+  (,) <$> newTVar True <*> newEmptyTMVar++syncWriteFunction :: SyncState -> C.CURL_write_callback+syncWriteFunction (active, chunk) b = +  atomically $ do+    readTVar active >>= \case+      False -> return C.CURL_WRITEFUNC_FAIL+      True -> putTMVar chunk b >> return C.CURL_WRITEFUNC_OK++
+ list-t-libcurl.cabal view
@@ -0,0 +1,61 @@+name:+  list-t-libcurl+version:+  0.2.0.0+synopsis:+  A "libcurl"-based streaming HTTP client+category:+  Streaming, HTTP+homepage:+  https://github.com/nikita-volkov/list-t-libcurl+bug-reports:+  https://github.com/nikita-volkov/list-t-libcurl/issues +author:+  Nikita Volkov <nikita.y.volkov@mail.ru>+maintainer:+  Nikita Volkov <nikita.y.volkov@mail.ru>+copyright:+  (c) 2015, Nikita Volkov+license:+  MIT+license-file:+  LICENSE+build-type:+  Simple+cabal-version:+  >=1.10+++source-repository head+  type:+    git+  location:+    git://github.com/nikita-volkov/list-t-libcurl.git+++library+  hs-source-dirs:+    library+  other-modules:+  exposed-modules:+    ListT.Libcurl+  ghc-options:+    -funbox-strict-fields+  default-extensions:+    Arrows, BangPatterns, ConstraintKinds, DataKinds, DefaultSignatures, DeriveDataTypeable, DeriveFoldable, DeriveFunctor, DeriveGeneric, DeriveTraversable, EmptyDataDecls, FlexibleContexts, FlexibleInstances, FunctionalDependencies, GADTs, GeneralizedNewtypeDeriving, ImpredicativeTypes, LambdaCase, LiberalTypeSynonyms, MultiParamTypeClasses, MultiWayIf, NoImplicitPrelude, NoMonomorphismRestriction, OverloadedStrings, PatternGuards, ParallelListComp, QuasiQuotes, RankNTypes, RecordWildCards, ScopedTypeVariables, StandaloneDeriving, TemplateHaskell, TupleSections, TypeFamilies, TypeOperators+  default-language:+    Haskell2010+  build-depends:+    template-haskell == 2.*,+    resource-pool == 0.2.*,+    stm == 2.4.*,+    curlhs == 0.1.*,++    bytestring >= 0.10 && < 0.11,++    list-t >= 0.4.5 && < 0.5,+    either == 4.*,+    +    mtl-prelude >= 1 && < 3,+    base-prelude >= 0.1.19 && < 0.2,+    base < 5