Implement getService and getLocation

This commit is contained in:
Aditya Manthramurthy 2017-01-04 09:36:28 +05:30
parent 9d6ec0f6e5
commit 00e9198e60
5 changed files with 109 additions and 19 deletions

View File

@ -8,24 +8,30 @@ import Network.Minio.Data
import Network.Minio.API import Network.Minio.API
import Control.Monad.Trans.Resource (runResourceT) import Control.Monad.Trans.Resource (runResourceT)
import qualified Data.Conduit as C -- import qualified Data.Conduit as C
import qualified Data.Conduit.List as CL -- import qualified Data.Conduit.List as CL
import qualified Network.HTTP.Conduit as NC -- import qualified Network.HTTP.Conduit as NC
main :: IO () main :: IO ()
main = do main = do
mc <- connect defaultConnectInfo mc <- connect defaultConnectInfo
t <- runResourceT $ runMinio mc $ do t <- runResourceT $ runMinio mc $ do
res <- getService res <- getService
liftIO $ print $ NC.responseStatus res print res
liftIO $ print $ NC.responseHeaders res -- case res of
-- Left e -> print e
-- Right res1 -> mapM_ print res1
-- liftIO $ print $ NC.responseStatus res
-- liftIO $ print $ NC.responseHeaders res
-- liftIO print $ NC.responseHeaders <$> res -- liftIO print $ NC.responseHeaders <$> res
-- let bodyE = NC.responseBody <$> res -- let bodyE = NC.responseBody <$> res
-- case bodyE of -- case bodyE of
-- Left x -> print x -- Left x -> print x
-- Right body -> body C.$$+- CL.mapM_ putStrLn -- Right body -> body C.$$+- CL.mapM_ putStrLn
-- body <- NC.responseBody <$> res -- body <- NC.responseBody <$> res
NC.responseBody res C.$$+- CL.mapM_ putStrLn -- NC.responseBody res C.$$+- CL.mapM_ putStrLn
res <- getLocation "test1"
print res
print "Hello" print "After runResourceT"
print t print t

View File

@ -22,6 +22,7 @@ library
, Network.Minio.Data.Time , Network.Minio.Data.Time
, Network.Minio.Sign.V4 , Network.Minio.Sign.V4
, Network.Minio.API , Network.Minio.API
, Network.Minio.XmlParser
other-modules: Lib.Prelude other-modules: Lib.Prelude
build-depends: base >= 4.7 && < 5 build-depends: base >= 4.7 && < 5
, protolude >= 0.1.6 && < 0.2 , protolude >= 0.1.6 && < 0.2
@ -30,6 +31,7 @@ library
, conduit , conduit
, containers , containers
, cryptonite , cryptonite
, errors
, http-client , http-client
, http-conduit , http-conduit
, http-types , http-types
@ -39,6 +41,7 @@ library
, time , time
, transformers , transformers
, transformers-base , transformers-base
, xml-conduit
default-language: Haskell2010 default-language: Haskell2010
default-extensions: FlexibleContexts default-extensions: FlexibleContexts
, FlexibleInstances , FlexibleInstances

View File

@ -5,6 +5,7 @@ module Network.Minio.API
, RequestInfo(..) , RequestInfo(..)
, runMinio , runMinio
, getService , getService
, getLocation
) where ) where
import qualified Network.HTTP.Types as HT import qualified Network.HTTP.Types as HT
@ -12,8 +13,6 @@ import Network.HTTP.Conduit (Response)
import qualified Network.HTTP.Conduit as NC import qualified Network.HTTP.Conduit as NC
import Network.HTTP.Types (Method, Header, Query) import Network.HTTP.Types (Method, Header, Query)
import Control.Monad.Trans.Resource (MonadResource, ResourceT, runResourceT)
import Lib.Prelude import Lib.Prelude
import qualified Data.Conduit as C import qualified Data.Conduit as C
@ -21,6 +20,7 @@ import qualified Data.Conduit as C
import Network.Minio.Data import Network.Minio.Data
import Network.Minio.Data.Crypto import Network.Minio.Data.Crypto
import Network.Minio.Sign.V4 import Network.Minio.Sign.V4
import Network.Minio.XmlParser
-- runRequestDebug r mgr = do -- runRequestDebug r mgr = do
-- print $ "runRequestDebug" -- print $ "runRequestDebug"
@ -34,6 +34,34 @@ import Network.Minio.Sign.V4
-- -- print $ NC.requestBody r -- -- print $ NC.requestBody r
-- NC.httpLbs r mgr -- NC.httpLbs r mgr
executeRequest :: RequestInfo -> Minio (Response LByteString)
executeRequest ri = do
let PayloadSingle pload = payload ri
phash = hashSHA256 pload
newRI = ri {
payloadHash = phash
, headers = ("x-amz-content-sha256", phash) : (headers ri)
}
ci <- asks mcConnInfo
reqHeaders <- liftIO $ signV4 ci newRI
mgr <- asks mcConnManager
let req = NC.defaultRequest {
NC.method = method newRI
, NC.secure = connectIsSecure ci
, NC.host = encodeUtf8 $ connectHost ci
, NC.port = connectPort ci
, NC.path = getPathFromRI ri
, NC.queryString = HT.renderQuery False $ queryParams ri
, NC.requestHeaders = reqHeaders
, NC.requestBody = NC.RequestBodyBS pload
}
NC.httpLbs req mgr
mkSRequest :: RequestInfo -> Minio (Response (C.ResumableSource Minio ByteString)) mkSRequest :: RequestInfo -> Minio (Response (C.ResumableSource Minio ByteString))
mkSRequest ri = do mkSRequest ri = do
let PayloadSingle pload = payload ri let PayloadSingle pload = payload ri
@ -60,15 +88,23 @@ mkSRequest ri = do
, NC.requestBody = NC.RequestBodyBS pload , NC.requestBody = NC.RequestBodyBS pload
} }
response <- NC.http req mgr NC.http req mgr
return response
requestInfo :: Method -> Maybe Bucket -> Maybe Object requestInfo :: Method -> Maybe Bucket -> Maybe Object
-> Query -> [Header] -> Payload -> Query -> [Header] -> Payload
-> RequestInfo -> RequestInfo
requestInfo m b o q h p = RequestInfo m b o q h p "" requestInfo m b o q h p = RequestInfo m b o q h p ""
-- getService :: Minio _ -- ResponseInfo getService :: Minio [BucketInfo]
getService = mkSRequest $ getService = do
requestInfo HT.methodGet Nothing Nothing [] [] $ resp <- executeRequest $
PayloadSingle "" requestInfo HT.methodGet Nothing Nothing [] [] $
PayloadSingle ""
parseListBuckets $ NC.responseBody resp
getLocation :: Bucket -> Minio Text
getLocation bucket = do
resp <- executeRequest $
requestInfo HT.methodGet (Just bucket) Nothing [("location", Nothing)] []
(PayloadSingle "")
parseLocation $ NC.responseBody resp

View File

@ -1,14 +1,15 @@
{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Network.Minio.Data module Network.Minio.Data
( ( ConnectInfo(..)
ConnectInfo(..)
, RequestInfo(..) , RequestInfo(..)
-- , ResponseInfo(..) -- , ResponseInfo(..)
, MinioConn(..) , MinioConn(..)
, Bucket , Bucket
, Object , Object
, BucketInfo(..)
, getPathFromRI , getPathFromRI
, Minio , Minio
, MinioErr(..)
, runMinio , runMinio
, defaultConnectInfo , defaultConnectInfo
, connect , connect
@ -40,9 +41,15 @@ defaultConnectInfo :: ConnectInfo
defaultConnectInfo = defaultConnectInfo =
ConnectInfo "localhost" 9000 "minio" "minio123" False "us-east-1" ConnectInfo "localhost" 9000 "minio" "minio123" False "us-east-1"
type Bucket = ByteString type Bucket = Text
type Object = Text type Object = Text
data BucketInfo = BucketInfo {
biName :: Bucket
, biCreationDate :: UTCTime
} deriving (Show, Eq)
data Payload = PayloadSingle ByteString data Payload = PayloadSingle ByteString
deriving (Show, Eq) deriving (Show, Eq)
@ -61,10 +68,11 @@ getPathFromRI :: RequestInfo -> ByteString
getPathFromRI ri = B.concat $ parts getPathFromRI ri = B.concat $ parts
where where
objPart = maybe [] (\o -> ["/", encodeUtf8 o]) $ object ri objPart = maybe [] (\o -> ["/", encodeUtf8 o]) $ object ri
parts = maybe ["/"] (\b -> "/" : b : objPart) $ bucket ri parts = maybe ["/"] (\b -> "/" : encodeUtf8 b : objPart) $ bucket ri
data MinioErr = MErrMsg ByteString data MinioErr = MErrMsg ByteString
| MErrHttp HttpException | MErrHttp HttpException
| MErrXml ByteString
deriving (Show) deriving (Show)
newtype Minio a = Minio { newtype Minio a = Minio {

View File

@ -0,0 +1,37 @@
module Network.Minio.XmlParser
( parseListBuckets
, parseLocation
) where
import Text.XML
import Text.XML.Cursor
import qualified Data.Text as T
import Data.Time
import Control.Error
import Lib.Prelude
import Network.Minio.Data
s3Name :: Text -> Name
s3Name s = Name s (Just "http://s3.amazonaws.com/doc/2006-03-01/") Nothing
s3TimeFormat = iso8601DateFormat $ Just "%T%QZ"
parseListBuckets :: (MonadError MinioErr m) => LByteString -> m [BucketInfo]
parseListBuckets xmldata = do
doc <- either (throwError . MErrXml . show) return $ parseLBS def xmldata
let cursor = fromDocument doc
names = cursor $// element (s3Name "Bucket") &//
element (s3Name "Name") &/ content
timeStrings = cursor $// element (s3Name "Bucket") &//
element (s3Name "CreationDate") &/ content
times <- either (throwError . MErrXml) return $
mapM (parseTimeM True defaultTimeLocale s3TimeFormat . T.unpack)
timeStrings
return $ map (\(n, t) -> BucketInfo n t) $ zip names times
parseLocation :: (MonadError MinioErr m) => LByteString -> m Text
parseLocation xmldata = do
doc <- either (throwError . MErrXml . show) return $ parseLBS def xmldata
return $ T.concat $ fromDocument doc $/ content