-- | Some handy functions for retrieving a web-page. module Geography.Geocoding.Google.Get (get, maybeGet, eitherGet, timeoutGet) where import Data.Char (intToDigit) import Control.Concurrent ( threadDelay, newEmptyMVar, myThreadId , forkIO, putMVar, killThread, takeMVar ) import Network.HTTP ( simpleHTTP, insertHeaders, Header (..), HeaderName (..) , Request (..), RequestMethod (..), rspBody ) import Network.URI (parseURI, URI) import System.Environment (getArgs) import System.Exit (exitFailure) import System.IO (hPutStrLn, stderr) import Control.Exception (catch, SomeException) err :: String -> IO a err msg = do hPutStrLn stderr msg exitFailure get :: URI -> IO String get uri = do eresp <- simpleHTTP $ insertHeaders [Header HdrAccept "*/*"] (Request uri GET [] "") case eresp of Left er -> fail $ show er Right res -> return $ rspBody res maybeGet :: URI -> IO (Maybe String) maybeGet uri = either (const Nothing) Just `fmap` eitherGet uri eitherGet :: URI -> IO (Either String String) eitherGet uri = timeoutGet uri -- 5 sec waitTimeout = 10000000 timeoutGet :: URI -> IO (Either String String) timeoutGet uri = do mv <- newEmptyMVar mid <- myThreadId tid1 <- forkIO $ do x <- get uri putMVar mv $ Right x `catch` (\ e -> putMVar mv . Left . show $ (e :: SomeException)) tid2 <- forkIO $ do threadDelay waitTimeout killThread tid1 putMVar mv (Left "timeout") takeMVar mv