packages feed

aeson-streams (empty) → 0.1.0

raw patch · 4 files changed

+230/−0 lines, 4 filesdep +HsOpenSSLdep +aesondep +attoparsecsetup-changed

Dependencies added: HsOpenSSL, aeson, attoparsec, base, bytestring, http-streams, io-streams

Files

+ LICENSE view
@@ -0,0 +1,27 @@+Copyright: (c) Vo Minh Thu, 2014.++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:+1. Redistributions of source code must retain the above copyright+   notice, this list of conditions and the following disclaimer.+2. Redistributions in binary form must reproduce the above copyright+   notice, this list of conditions and the following disclaimer in the+   documentation and/or other materials provided with the distribution.+3. Neither the name of the author nor the names of his contributors+   may be used to endorse or promote products derived from this software+   without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+SUCH DAMAGE.
+ Network/Aeson/Client.hs view
@@ -0,0 +1,174 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TupleSections #-}+module Network.Aeson.Client where++import Data.Aeson hiding (Result)+import Data.Attoparsec.ByteString (parseWith, IResult(..))+import qualified Data.ByteString.Lazy.Char8 as LB+import qualified Data.ByteString.Char8 as B+import Data.Maybe (fromMaybe)+import Network.Http.Client+import OpenSSL (withOpenSSL)+import System.IO (hFlush, hPutStrLn, stderr)+import qualified System.IO.Streams as Streams++-- | Execute a GET agains the specified URI (e.g. `/v1`) using the+-- supplied parameters.+apiGet :: FromJSON a =>+  Maybe (B.ByteString, B.ByteString)+  -> B.ByteString+  -> B.ByteString+  -> [(B.ByteString, Maybe B.ByteString)] -> IO (Maybe a)+apiGet mbasic base uri parameters = withOpenSSL $ do+  let url = B.concat [uri, queryString parameters]+  q <- buildRequest $ do+    http GET url+    maybe (return ()) (uncurry setAuthorizationBasic) mbasic++  c <- establishConnection base+  -- debug q+  sendRequest c q emptyBody+  receiveResponse' c++-- | Execute a POST agains the specified URI (e.g. `/v1`) using the+-- supplied parameters.+apiPost :: FromJSON a =>+  Maybe (B.ByteString, B.ByteString)+  -> B.ByteString+  -> B.ByteString+  -> [(B.ByteString, Maybe B.ByteString)] -> LB.ByteString -> IO (Maybe a)+apiPost mbasic base uri parameters body = withOpenSSL $ do+  let url = B.concat [uri, queryString parameters]+  q <- buildRequest $ do+    http POST url+    maybe (return ()) (uncurry setAuthorizationBasic) mbasic+    setContentLength (fromIntegral $ LB.length body)+    setContentType "application/json"++  c <- establishConnection base+  -- debug q+  body' <- Streams.fromLazyByteString body+  sendRequest c q (inputStreamBody body')+  receiveResponse' c++-- | Execute a DELETE agains the specified URI (e.g. `/v1`) using the+-- supplied parameters.+apiDelete :: FromJSON a =>+  Maybe (B.ByteString, B.ByteString)+  -> B.ByteString+  -> B.ByteString+  -> [(B.ByteString, Maybe B.ByteString)] -> IO (Result a)+apiDelete mbasic base uri parameters = withOpenSSL $ do+  let url = B.concat [uri, queryString parameters]+  q <- buildRequest $ do+    http DELETE url+    maybe (return ()) (uncurry setAuthorizationBasic) mbasic++  c <- establishConnection base+  -- debug q+  sendRequest c q emptyBody+  -- TODO assert 204 for upcloud++  r <- receiveResponse c $ \p' i -> do+    case getStatusCode p' of+      204 -> return Ok+      _ -> do+        x <- Streams.read i+        let more = Streams.read i >>= return . fromMaybe ""+        p <- parseWith more json $ fromMaybe "" x+        case p of+          Done _ value -> do+            -- debug value+            case fromJSON value of+              Success value' -> do+                return $ Value value'+              _ -> return JsonFailure+          _ -> return ParseFailure+  closeConnection c+  return r++data Result a =+    Ok+  -- ^ Success and empty result+  | Value a+  -- ^ Succes and non-empty result+  | JsonFailure+  -- ^ Can't turn JSON into a proper result+  | ParseFailure+  -- ^ Can't parse JSON+  deriving Show++-- | Execute a PUT agains the specified URI using the+-- supplied parameters.+apiPut ::+  Maybe (B.ByteString, B.ByteString)+  -> B.ByteString+  -> B.ByteString+  -> [(B.ByteString, Maybe B.ByteString)]+  -> LB.ByteString+  -> IO ()+apiPut mbasic base uri parameters body = withOpenSSL $ do+  let url = B.concat [uri, queryString parameters]+  q <- buildRequest $ do+    http PUT url+    setContentLength (fromIntegral $ LB.length body)+    setContentType "application/json"+    maybe (return ()) (uncurry setAuthorizationBasic) mbasic++  c <- establishConnection base+  -- debug q+  body' <- Streams.fromLazyByteString body+  sendRequest c q (inputStreamBody body')+  -- TODO assert 204 for upcloud++-- | Execute a PATCH agains the specified URI using the+-- supplied parameters.+apiPatch ::+  Maybe (B.ByteString, B.ByteString)+  -> B.ByteString+  -> B.ByteString+  -> [(B.ByteString, Maybe B.ByteString)]+  -> LB.ByteString+  -> IO ()+apiPatch mbasic base uri parameters body = withOpenSSL $ do+  let url = B.concat [uri, queryString parameters]+  q <- buildRequest $ do+    http PATCH url+    setContentLength (fromIntegral $ LB.length body)+    setContentType "application/json"+    maybe (return ()) (uncurry setAuthorizationBasic) mbasic++  c <- establishConnection base+  -- debug q+  body' <- Streams.fromLazyByteString body+  sendRequest c q (inputStreamBody body')+  -- TODO assert 204 for upcloud++receiveResponse' :: FromJSON a => Connection -> IO (Maybe a)+receiveResponse' c = do+  r <- receiveResponse c $ \_ i -> do+    x <- Streams.read i+    let more = Streams.read i >>= return . fromMaybe ""+    p <- parseWith more json $ fromMaybe "" x+    case p of+      Done _ value -> do+        -- debug value+        case fromJSON value of+          Success value' -> do+            return $ Just value'+          _ -> return Nothing+      _ -> return Nothing+  closeConnection c+  return r++queryString :: [(B.ByteString, Maybe B.ByteString)] -> B.ByteString+queryString [] = ""+queryString xs = B.cons '?' . B.intercalate "&" . map f $ xs+  where f (a, Just b) = B.concat [a, "=", b]+        f (a, _) = a++debug :: Show a => a -> IO ()+debug s = do+  hPutStrLn stderr $ show s+  hFlush stderr
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ aeson-streams.cabal view
@@ -0,0 +1,27 @@+name:                aeson-streams+version:             0.1.0+Cabal-Version:       >= 1.8+synopsis:            An HTTP client library for JSON-based APIs+description:         An HTTP client library for JSON-based APIs using aeson and http-streams.+category:            Web+license:             BSD3+license-file:        LICENSE+author:              Vo Minh Thu+maintainer:          thu@hypered.io+build-type:          Simple+homepage:            https://github.com/noteed/aeson-streams++source-repository head+  type: git+  location: git://github.com/noteed/aeson-streams.git++library+  build-depends:       aeson == 0.6.*,+                       attoparsec == 0.10.*,+                       base == 4.*,+                       bytestring > 0.9 && < 0.11,+                       HsOpenSSL == 0.10.*,+                       http-streams >= 0.7 && <= 0.9,+                       io-streams == 1.1.*+  exposed-modules:     Network.Aeson.Client+  ghc-options:         -Wall