{-# LANGUAGE OverloadedStrings #-}

module Database.HSparql.Connection
  ( Database.HSparql.Connection.EndPoint,
    BindingValue (..),

    -- * submit queries using HSparql DSL
    selectQuery,
    constructQuery,
    askQuery,
    updateQuery,
    describeQuery,

    -- * submit queries using raw SPARQL strings
    selectQueryRaw,
    constructQueryRaw,
    askQueryRaw,
    updateQueryRaw,
    describeQueryRaw,
  )
where

import Control.Monad
import Control.Monad.IO.Class
import qualified Data.ByteString.Char8 as B
import qualified Data.ByteString.Lazy.Char8 as LB
import Data.Maybe (isJust, mapMaybe)
import qualified Data.RDF as RDF
import qualified Data.Text as T
import qualified Data.Text.Encoding as E
import qualified Data.Text.Encoding as T
import Database.HSparql.QueryGenerator
import Network.Connection (TLSSettings (..))
import Network.HTTP
import Network.HTTP.Conduit
import Network.HTTP.Types.Header
import Text.RDF.RDF4H.TurtleParser
import Text.XML.Light

-- | URI of the SPARQL endpoint.
type EndPoint = String

-- | Local representations of incoming XML results.
data BindingValue
  = -- | RDF Node (UNode, BNode, LNode)
    Bound RDF.Node
  | -- | Unbound result value
    Unbound
  deriving (Int -> BindingValue -> ShowS
[BindingValue] -> ShowS
BindingValue -> String
(Int -> BindingValue -> ShowS)
-> (BindingValue -> String)
-> ([BindingValue] -> ShowS)
-> Show BindingValue
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [BindingValue] -> ShowS
$cshowList :: [BindingValue] -> ShowS
show :: BindingValue -> String
$cshow :: BindingValue -> String
showsPrec :: Int -> BindingValue -> ShowS
$cshowsPrec :: Int -> BindingValue -> ShowS
Show, BindingValue -> BindingValue -> Bool
(BindingValue -> BindingValue -> Bool)
-> (BindingValue -> BindingValue -> Bool) -> Eq BindingValue
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: BindingValue -> BindingValue -> Bool
$c/= :: BindingValue -> BindingValue -> Bool
== :: BindingValue -> BindingValue -> Bool
$c== :: BindingValue -> BindingValue -> Bool
Eq)

-- | Base 'QName' for results with a SPARQL-result URI specified.
sparqlResult :: String -> QName
sparqlResult :: String -> QName
sparqlResult String
s = (String -> QName
unqual String
s) {qURI :: Maybe String
qURI = String -> Maybe String
forall a. a -> Maybe a
Just String
"http://www.w3.org/2005/sparql-results#"}

-- | Transform the 'String' result from the HTTP request into a two-dimensional
--   table storing the bindings for each variable in each row.
structureContent :: String -> Maybe [[BindingValue]]
structureContent :: String -> Maybe [[BindingValue]]
structureContent String
s =
  do
    Element
e <- Maybe Element
doc
    [[BindingValue]] -> Maybe [[BindingValue]]
forall (m :: * -> *) a. Monad m => a -> m a
return ([[BindingValue]] -> Maybe [[BindingValue]])
-> [[BindingValue]] -> Maybe [[BindingValue]]
forall a b. (a -> b) -> a -> b
$ (Element -> [BindingValue]) -> [Element] -> [[BindingValue]]
forall a b. (a -> b) -> [a] -> [b]
map ([String] -> Element -> [BindingValue]
projectResult ([String] -> Element -> [BindingValue])
-> [String] -> Element -> [BindingValue]
forall a b. (a -> b) -> a -> b
$ Element -> [String]
vars Element
e) ([Element] -> [[BindingValue]]) -> [Element] -> [[BindingValue]]
forall a b. (a -> b) -> a -> b
$ QName -> Element -> [Element]
findElements (String -> QName
sparqlResult String
"result") Element
e
  where
    doc :: Maybe Element
    doc :: Maybe Element
doc = String -> Maybe Element
forall s. XmlSource s => s -> Maybe Element
parseXMLDoc String
s

    vars :: Element -> [String]
    vars :: Element -> [String]
vars = (Element -> Maybe String) -> [Element] -> [String]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (QName -> Element -> Maybe String
findAttr (QName -> Element -> Maybe String)
-> QName -> Element -> Maybe String
forall a b. (a -> b) -> a -> b
$ String -> QName
unqual String
"name") ([Element] -> [String])
-> (Element -> [Element]) -> Element -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. QName -> Element -> [Element]
findElements (String -> QName
sparqlResult String
"variable")

    projectResult :: [String] -> Element -> [BindingValue]
    projectResult :: [String] -> Element -> [BindingValue]
projectResult [String]
vs Element
e = (String -> BindingValue) -> [String] -> [BindingValue]
forall a b. (a -> b) -> [a] -> [b]
map String -> BindingValue
pVar [String]
vs
      where
        pVar :: String -> BindingValue
pVar String
v = BindingValue
-> (Element -> BindingValue) -> Maybe Element -> BindingValue
forall b a. b -> (a -> b) -> Maybe a -> b
maybe BindingValue
Unbound (Element -> BindingValue
value (Element -> BindingValue)
-> (Element -> Element) -> Element -> BindingValue
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Element] -> Element
forall a. [a] -> a
head ([Element] -> Element)
-> (Element -> [Element]) -> Element -> Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Element -> [Element]
elChildren) (Maybe Element -> BindingValue) -> Maybe Element -> BindingValue
forall a b. (a -> b) -> a -> b
$ (Element -> Bool) -> Element -> Maybe Element
filterElement (String -> Element -> Bool
pred_ String
v) Element
e
        pred_ :: String -> Element -> Bool
pred_ String
v Element
e' = Maybe () -> Bool
forall a. Maybe a -> Bool
isJust (Maybe () -> Bool) -> Maybe () -> Bool
forall a b. (a -> b) -> a -> b
$ do
          String
a <- QName -> Element -> Maybe String
findAttr (String -> QName
unqual String
"name") Element
e'
          Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> Maybe ()) -> Bool -> Maybe ()
forall a b. (a -> b) -> a -> b
$ String
a String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
v

    value :: Element -> BindingValue
    value :: Element -> BindingValue
value Element
e =
      case QName -> String
qName (Element -> QName
elName Element
e) of
        String
"uri" -> Node -> BindingValue
Bound (Node -> BindingValue) -> Node -> BindingValue
forall a b. (a -> b) -> a -> b
$ Text -> Node
RDF.unode (Text -> Node) -> Text -> Node
forall a b. (a -> b) -> a -> b
$ String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ Element -> String
strContent Element
e
        String
"literal" -> case QName -> Element -> Maybe String
findAttr (String -> QName
unqual String
"datatype") Element
e of
          Just String
dt -> Node -> BindingValue
Bound (Node -> BindingValue) -> Node -> BindingValue
forall a b. (a -> b) -> a -> b
$ LValue -> Node
RDF.lnode (LValue -> Node) -> LValue -> Node
forall a b. (a -> b) -> a -> b
$ Text -> Text -> LValue
RDF.typedL (String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ Element -> String
strContent Element
e) (String -> Text
T.pack String
dt)
          Maybe String
Nothing -> case QName -> Element -> Maybe String
findAttr QName
langAttr Element
e of
            Just String
lang_ -> Node -> BindingValue
Bound (Node -> BindingValue) -> Node -> BindingValue
forall a b. (a -> b) -> a -> b
$ LValue -> Node
RDF.lnode (LValue -> Node) -> LValue -> Node
forall a b. (a -> b) -> a -> b
$ Text -> Text -> LValue
RDF.plainLL (String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ Element -> String
strContent Element
e) (String -> Text
T.pack String
lang_)
            Maybe String
Nothing -> Node -> BindingValue
Bound (Node -> BindingValue) -> Node -> BindingValue
forall a b. (a -> b) -> a -> b
$ LValue -> Node
RDF.lnode (LValue -> Node) -> LValue -> Node
forall a b. (a -> b) -> a -> b
$ Text -> LValue
RDF.plainL (String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ Element -> String
strContent Element
e)
        -- TODO: what about blank nodes?
        String
_ -> BindingValue
Unbound

    langAttr :: QName
    langAttr :: QName
langAttr = QName
blank_name {qName :: String
qName = String
"lang", qPrefix :: Maybe String
qPrefix = String -> Maybe String
forall a. a -> Maybe a
Just String
"xml"}

-- | Parses the response from a SPARQL ASK query. Either "true" or "false" is expected
parseAsk :: String -> Bool
parseAsk :: String -> Bool
parseAsk String
s
  | String
s' String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"true" Bool -> Bool -> Bool
|| String
s' String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"yes" = Bool
True
  | String
s' String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"false" Bool -> Bool -> Bool
|| String
s' String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"no" = Bool
False
  | Bool
otherwise = String -> Bool
forall a. HasCallStack => String -> a
error (String -> Bool) -> String -> Bool
forall a b. (a -> b) -> a -> b
$ String
"Unexpected Ask response: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
s
  where
    s' :: String
s' = ShowS
forall a. [a] -> [a]
reverse ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$ (Char -> Bool) -> ShowS
forall a. (a -> Bool) -> [a] -> [a]
dropWhile (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'\n') ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$ ShowS
forall a. [a] -> [a]
reverse String
s

-- | Parses the response from a SPARQL UPDATE query.  An empty body is expected
parseUpdate :: String -> Bool
parseUpdate :: String -> Bool
parseUpdate String
s
  | String
s String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"" = Bool
True
  | Bool
otherwise = String -> Bool
forall a. HasCallStack => String -> a
error (String -> Bool) -> String -> Bool
forall a b. (a -> b) -> a -> b
$ String
"Unexpected Update response: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
s

-- | Connect to remote 'EndPoint' and find all possible bindings for the
--  'Variable's in the 'SelectQueryRaw action.
selectQuery :: Database.HSparql.Connection.EndPoint -> Query SelectQuery -> IO (Maybe [[BindingValue]])
selectQuery :: String -> Query SelectQuery -> IO (Maybe [[BindingValue]])
selectQuery String
ep Query SelectQuery
q = String -> String -> IO (Maybe [[BindingValue]])
selectQueryRaw String
ep (Query SelectQuery -> String
createSelectQuery Query SelectQuery
q)

-- | Connect to remote 'EndPoint' and find all possible bindings for the
--   'Variable's in the 'SelectQueryRaw action.
askQuery :: Database.HSparql.Connection.EndPoint -> Query AskQuery -> IO Bool
askQuery :: String -> Query AskQuery -> IO Bool
askQuery String
ep Query AskQuery
q = String -> String -> IO Bool
askQueryRaw String
ep (Query AskQuery -> String
createAskQuery Query AskQuery
q)

-- | Connect to remote 'EndPoint' and find all possible bindings for the
--   'Variable's in the 'SelectQueryRaw action.
updateQuery :: Database.HSparql.Connection.EndPoint -> Query UpdateQuery -> IO Bool
updateQuery :: String -> Query UpdateQuery -> IO Bool
updateQuery String
ep Query UpdateQuery
q = String -> String -> IO Bool
updateQueryRaw String
ep (Query UpdateQuery -> String
createUpdateQuery Query UpdateQuery
q)

-- | Connect to remote 'EndPoint' and construct 'TriplesGraph' from given
--   'ConstructQueryRaw action. /Provisional implementation/.
constructQuery :: (RDF.Rdf a) => Database.HSparql.Connection.EndPoint -> Query ConstructQuery -> IO (RDF.RDF a)
constructQuery :: String -> Query ConstructQuery -> IO (RDF a)
constructQuery String
ep Query ConstructQuery
q = String -> String -> IO (RDF a)
forall a. Rdf a => String -> String -> IO (RDF a)
constructQueryRaw String
ep (Query ConstructQuery -> String
createConstructQuery Query ConstructQuery
q)

-- | Connect to remote 'EndPoint' and construct 'TriplesGraph' from given
--   'ConstructQueryRaw action. /Provisional implementation/.
describeQuery :: (RDF.Rdf a) => Database.HSparql.Connection.EndPoint -> Query DescribeQuery -> IO (RDF.RDF a)
describeQuery :: String -> Query DescribeQuery -> IO (RDF a)
describeQuery String
ep Query DescribeQuery
q = String -> String -> IO (RDF a)
forall a. Rdf a => String -> String -> IO (RDF a)
describeQueryRaw String
ep (Query DescribeQuery -> String
createDescribeQuery Query DescribeQuery
q)

selectQueryRaw :: Database.HSparql.Connection.EndPoint -> String -> IO (Maybe [[BindingValue]])
selectQueryRaw :: String -> String -> IO (Maybe [[BindingValue]])
selectQueryRaw String
ep String
q = do
  let uri :: String
uri = String
ep String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"?" String -> ShowS
forall a. [a] -> [a] -> [a]
++ [(String, String)] -> String
urlEncodeVars [(String
"query", String
q)]
      h1 :: (HeaderName, ByteString)
h1 = (HeaderName
hAccept, ByteString
"application/sparql-results+xml")
      h2 :: (HeaderName, ByteString)
h2 = (HeaderName
hUserAgent, ByteString
"hsparql-client")
  Request
request' <- String -> IO Request
forall (m :: * -> *). MonadThrow m => String -> m Request
parseRequest String
uri
  let request :: Request
request =
        Request
request'
          { method :: ByteString
method = ByteString
"GET",
            requestHeaders :: RequestHeaders
requestHeaders = [(HeaderName, ByteString)
h1, (HeaderName, ByteString)
h2]
          }
  let settings :: ManagerSettings
settings = TLSSettings -> Maybe SockSettings -> ManagerSettings
mkManagerSettings (Bool -> Bool -> Bool -> TLSSettings
TLSSettingsSimple Bool
True Bool
False Bool
False) Maybe SockSettings
forall a. Maybe a
Nothing
  Manager
manager <- IO Manager -> IO Manager
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Manager -> IO Manager) -> IO Manager -> IO Manager
forall a b. (a -> b) -> a -> b
$ ManagerSettings -> IO Manager
newManager ManagerSettings
settings
  Response ByteString
resp <- Request -> Manager -> IO (Response ByteString)
forall (m :: * -> *).
MonadIO m =>
Request -> Manager -> m (Response ByteString)
httpLbs Request
request Manager
manager
  Maybe [[BindingValue]] -> IO (Maybe [[BindingValue]])
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe [[BindingValue]] -> IO (Maybe [[BindingValue]]))
-> Maybe [[BindingValue]] -> IO (Maybe [[BindingValue]])
forall a b. (a -> b) -> a -> b
$ String -> Maybe [[BindingValue]]
structureContent (ByteString -> String
LB.unpack (Response ByteString -> ByteString
forall body. Response body -> body
responseBody Response ByteString
resp))

askQueryRaw :: Database.HSparql.Connection.EndPoint -> String -> IO Bool
askQueryRaw :: String -> String -> IO Bool
askQueryRaw String
ep String
q = do
  let uri :: String
uri = String
ep String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"?" String -> ShowS
forall a. [a] -> [a] -> [a]
++ [(String, String)] -> String
urlEncodeVars [(String
"query", String
q)]
      h1 :: (HeaderName, ByteString)
h1 = (HeaderName
hUserAgent, ByteString
"hsparql-client")
      h2 :: (HeaderName, ByteString)
h2 = (HeaderName
hAccept, ByteString
"text/plain")
      h3 :: (HeaderName, ByteString)
h3 = (HeaderName
hAccept, ByteString
"text/boolean")
      h4 :: (HeaderName, ByteString)
h4 = (HeaderName
hAcceptCharset, ByteString
"utf-8")
  Request
request' <- String -> IO Request
forall (m :: * -> *). MonadThrow m => String -> m Request
parseRequest String
uri
  let request :: Request
request =
        Request
request'
          { method :: ByteString
method = ByteString
"GET",
            requestHeaders :: RequestHeaders
requestHeaders = [(HeaderName, ByteString)
h1, (HeaderName, ByteString)
h2, (HeaderName, ByteString)
h3, (HeaderName, ByteString)
h4]
          }
  let settings :: ManagerSettings
settings = TLSSettings -> Maybe SockSettings -> ManagerSettings
mkManagerSettings (Bool -> Bool -> Bool -> TLSSettings
TLSSettingsSimple Bool
True Bool
False Bool
False) Maybe SockSettings
forall a. Maybe a
Nothing
  Manager
manager <- IO Manager -> IO Manager
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Manager -> IO Manager) -> IO Manager -> IO Manager
forall a b. (a -> b) -> a -> b
$ ManagerSettings -> IO Manager
newManager ManagerSettings
settings
  Response ByteString
resp <- Request -> Manager -> IO (Response ByteString)
forall (m :: * -> *).
MonadIO m =>
Request -> Manager -> m (Response ByteString)
httpLbs Request
request Manager
manager
  Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> IO Bool) -> Bool -> IO Bool
forall a b. (a -> b) -> a -> b
$ String -> Bool
parseAsk (ByteString -> String
LB.unpack (Response ByteString -> ByteString
forall body. Response body -> body
responseBody Response ByteString
resp))

updateQueryRaw :: Database.HSparql.Connection.EndPoint -> String -> IO Bool
updateQueryRaw :: String -> String -> IO Bool
updateQueryRaw String
ep String
q = do
  let uri :: String
uri = String
ep
      body :: String
body = String
q
      h1 :: (HeaderName, ByteString)
h1 = (HeaderName
hContentLength, String -> ByteString
B.pack (Int -> String
forall a. Show a => a -> String
show (String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
body)))
      h2 :: (HeaderName, ByteString)
h2 = (HeaderName
hContentType, ByteString
"application/sparql-update")
      h3 :: (HeaderName, ByteString)
h3 = (HeaderName
hUserAgent, ByteString
"hsparql-client")
  Request
request' <- String -> IO Request
forall (m :: * -> *). MonadThrow m => String -> m Request
parseRequest String
uri
  let request :: Request
request =
        Request
request'
          { method :: ByteString
method = ByteString
"POST",
            requestHeaders :: RequestHeaders
requestHeaders = [(HeaderName, ByteString)
h1, (HeaderName, ByteString)
h2, (HeaderName, ByteString)
h3],
            requestBody :: RequestBody
requestBody = ByteString -> RequestBody
RequestBodyBS (Text -> ByteString
T.encodeUtf8 (String -> Text
T.pack String
body))
          }
  let settings :: ManagerSettings
settings = TLSSettings -> Maybe SockSettings -> ManagerSettings
mkManagerSettings (Bool -> Bool -> Bool -> TLSSettings
TLSSettingsSimple Bool
True Bool
False Bool
False) Maybe SockSettings
forall a. Maybe a
Nothing
  Manager
manager <- IO Manager -> IO Manager
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Manager -> IO Manager) -> IO Manager -> IO Manager
forall a b. (a -> b) -> a -> b
$ ManagerSettings -> IO Manager
newManager ManagerSettings
settings
  Response ByteString
resp <- Request -> Manager -> IO (Response ByteString)
forall (m :: * -> *).
MonadIO m =>
Request -> Manager -> m (Response ByteString)
httpLbs Request
request Manager
manager
  Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> IO Bool) -> Bool -> IO Bool
forall a b. (a -> b) -> a -> b
$ String -> Bool
parseUpdate (ByteString -> String
LB.unpack (Response ByteString -> ByteString
forall body. Response body -> body
responseBody Response ByteString
resp))

constructQueryRaw :: (RDF.Rdf a) => Database.HSparql.Connection.EndPoint -> String -> IO (RDF.RDF a)
constructQueryRaw :: String -> String -> IO (RDF a)
constructQueryRaw String
ep String
q = do
  let uri :: String
uri = String
ep String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"?" String -> ShowS
forall a. [a] -> [a] -> [a]
++ [(String, String)] -> String
urlEncodeVars [(String
"query", String
q)]
  Either ParseFailure (RDF a)
rdfGraph <- String -> IO (Either ParseFailure (RDF a))
forall a. Rdf a => String -> IO (Either ParseFailure (RDF a))
httpCallForRdf String
uri
  case Either ParseFailure (RDF a)
rdfGraph of
    Left ParseFailure
e -> String -> IO (RDF a)
forall a. HasCallStack => String -> a
error (String -> IO (RDF a)) -> String -> IO (RDF a)
forall a b. (a -> b) -> a -> b
$ ParseFailure -> String
forall a. Show a => a -> String
show ParseFailure
e
    Right RDF a
graph -> RDF a -> IO (RDF a)
forall (m :: * -> *) a. Monad m => a -> m a
return RDF a
graph

describeQueryRaw :: (RDF.Rdf a) => Database.HSparql.Connection.EndPoint -> String -> IO (RDF.RDF a)
describeQueryRaw :: String -> String -> IO (RDF a)
describeQueryRaw String
ep String
q = do
  let uri :: String
uri = String
ep String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"?" String -> ShowS
forall a. [a] -> [a] -> [a]
++ [(String, String)] -> String
urlEncodeVars [(String
"query", String
q)]
  Either ParseFailure (RDF a)
rdfGraph <- String -> IO (Either ParseFailure (RDF a))
forall a. Rdf a => String -> IO (Either ParseFailure (RDF a))
httpCallForRdf String
uri
  case Either ParseFailure (RDF a)
rdfGraph of
    Left ParseFailure
e -> String -> IO (RDF a)
forall a. HasCallStack => String -> a
error (String -> IO (RDF a)) -> String -> IO (RDF a)
forall a b. (a -> b) -> a -> b
$ ParseFailure -> String
forall a. Show a => a -> String
show ParseFailure
e
    Right RDF a
graph -> RDF a -> IO (RDF a)
forall (m :: * -> *) a. Monad m => a -> m a
return RDF a
graph

-- | Takes a generated uri and makes simple HTTP request,
--  asking for RDF N3 serialization. Returns either 'ParseFailure' or 'RDF'
httpCallForRdf :: RDF.Rdf a => String -> IO (Either RDF.ParseFailure (RDF.RDF a))
httpCallForRdf :: String -> IO (Either ParseFailure (RDF a))
httpCallForRdf String
uri = do
  let h1 :: (HeaderName, ByteString)
h1 = (HeaderName
hUserAgent, ByteString
"hsparql-client")
      h2 :: (HeaderName, ByteString)
h2 = (HeaderName
hAccept, ByteString
"text/turtle")
  Request
request' <- String -> IO Request
forall (m :: * -> *). MonadThrow m => String -> m Request
parseRequest String
uri
  let request :: Request
request =
        Request
request'
          { method :: ByteString
method = ByteString
"GET",
            requestHeaders :: RequestHeaders
requestHeaders = [(HeaderName, ByteString)
h1, (HeaderName, ByteString)
h2]
          }
  let settings :: ManagerSettings
settings = TLSSettings -> Maybe SockSettings -> ManagerSettings
mkManagerSettings (Bool -> Bool -> Bool -> TLSSettings
TLSSettingsSimple Bool
True Bool
False Bool
False) Maybe SockSettings
forall a. Maybe a
Nothing
  Manager
manager <- IO Manager -> IO Manager
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Manager -> IO Manager) -> IO Manager -> IO Manager
forall a b. (a -> b) -> a -> b
$ ManagerSettings -> IO Manager
newManager ManagerSettings
settings
  Response ByteString
resp <- Request -> Manager -> IO (Response ByteString)
forall (m :: * -> *).
MonadIO m =>
Request -> Manager -> m (Response ByteString)
httpLbs Request
request Manager
manager
  Either ParseFailure (RDF a) -> IO (Either ParseFailure (RDF a))
forall (m :: * -> *) a. Monad m => a -> m a
return (Either ParseFailure (RDF a) -> IO (Either ParseFailure (RDF a)))
-> Either ParseFailure (RDF a) -> IO (Either ParseFailure (RDF a))
forall a b. (a -> b) -> a -> b
$ TurtleParser -> Text -> Either ParseFailure (RDF a)
forall p a.
(RdfParser p, Rdf a) =>
p -> Text -> Either ParseFailure (RDF a)
RDF.parseString (Maybe BaseUrl -> Maybe Text -> TurtleParser
TurtleParser Maybe BaseUrl
forall a. Maybe a
Nothing Maybe Text
forall a. Maybe a
Nothing) (Text -> Either ParseFailure (RDF a))
-> Text -> Either ParseFailure (RDF a)
forall a b. (a -> b) -> a -> b
$ ByteString -> Text
E.decodeUtf8 (ByteString -> ByteString
LB.toStrict (Response ByteString -> ByteString
forall body. Response body -> body
responseBody Response ByteString
resp))