module Network.Http.ClientFacade (getRequest, ajaxRequest) where
import Control.Exception (bracket)
import qualified Data.ByteString.Char8 as BC
import Data.IORef (IORef, newIORef, readIORef, writeIORef)
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import Data.Word (Word16)
import qualified Network.Http.Client as C
import qualified Network.URI as U
import OpenSSL.Session (SSLContext)
import qualified System.IO.Unsafe as Unsafe (unsafePerformIO)
import Network.URI.Util
getRequest :: BC.ByteString -> IO BC.ByteString
getRequest = doRequest C.concatHandler
where
doRequest handler url = do
bracket
(openConnection url)
(C.closeConnection)
(process)
where
u = parseURL url
q = C.buildRequest1 $ do
C.http C.GET (path u)
C.setAccept "*/*" where
path :: U.URI -> BC.ByteString
path u' =
case url' of
"" -> "/"
_ -> url'
where
url' = T.encodeUtf8 $! T.pack $! concat [U.uriPath u', U.uriQuery u', U.uriFragment u']
process c = do
C.sendRequest c q C.emptyBody
C.receiveResponse c handler
parseURL :: BC.ByteString -> U.URI
parseURL = toURI . T.unpack . T.decodeUtf8
openConnection :: C.URL -> IO C.Connection
openConnection = establish . parseURL
where
establish u =
case scheme of
"http:" -> do
C.openConnection host port
"https:" -> do
ctx <- readIORef global
C.openConnectionSSL ctx host ports
_ -> error ("Unknown URI scheme " ++ scheme)
where
scheme = U.uriScheme u
auth = case U.uriAuthority u of
Just x -> x
Nothing -> U.URIAuth "" "localhost" ""
host = BC.pack (U.uriRegName auth)
port = case U.uriPort auth of
"" -> 80
_ -> read $ tail $ U.uriPort auth :: Word16
ports = case U.uriPort auth of
"" -> 443
_ -> read $ tail $ U.uriPort auth :: Word16
global :: IORef SSLContext
global = Unsafe.unsafePerformIO $ do
ctx <- C.baselineContextSSL
newIORef ctx
ajaxRequest :: BC.ByteString -> [(BC.ByteString, BC.ByteString)] -> IO BC.ByteString
ajaxRequest = postRequest C.concatHandler ajaxRequestChanges where
ajaxRequestChanges = do
C.setContentType "application/x-www-form-urlencoded; charset=UTF-8"
C.setAccept "application/json, text/javascript, */*"
C.setHeader "X-Requested-With" "XMLHttpRequest"
postRequest handler requestChanges url formParams = do
bracket
(openConnection url)
(C.closeConnection)
(process)
where
u = parseURL url
q = C.buildRequest1 $ do
C.http C.POST (path u)
C.setAccept $ BC.pack "*/*"
C.setContentType $ BC.pack "application/x-www-form-urlencoded"
requestChanges where
path :: U.URI -> BC.ByteString
path u' =
case url' of
"" -> "/"
_ -> url'
where
url' = T.encodeUtf8 $! T.pack $! concat [U.uriPath u', U.uriQuery u', U.uriFragment u']
process c = do
_ <- C.sendRequest c q (C.encodedFormBody formParams)
x <- C.receiveResponse c handler
return x