brok-1.0.0: src/Brok/IO/Http.hs
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
module Brok.IO.Http
( check
, mkManager
) where
import ClassyPrelude
import Control.Concurrent (threadDelay)
import Network.Connection (TLSSettings (TLSSettingsSimple))
import Network.HTTP.Client (HttpExceptionContent (InternalException), Manager, httpNoBody,
newManager)
import Network.HTTP.Client.TLS (mkManagerSettings)
import Network.HTTP.Simple (HttpException, HttpException (..), Request, addRequestHeader,
getResponseStatusCode, parseRequest, setRequestMethod)
import Brok.IO.CLI (replace)
import Brok.Types.Brok (Brok, appTLSManager)
import Brok.Types.Link
import Brok.Types.URL (URL)
type StatusCode = Either HttpException Int
mkManager :: Bool -> IO Manager
mkManager checkCerts = do
let tls = TLSSettingsSimple (not checkCerts) False False
let settings = mkManagerSettings tls Nothing
newManager settings
setHeaders :: Request -> Request
setHeaders = addRequestHeader "User-Agent" "smallhadroncollider/brok"
makeRequest :: Integer -> ByteString -> URL -> Brok StatusCode
makeRequest delay method url = do
manager <- asks appTLSManager
lift . try $ do
request <- setHeaders . setRequestMethod method <$> parseRequest (unpack url)
threadDelay (fromIntegral delay * 1000) -- wait for a little while
getResponseStatusCode <$> httpNoBody request manager
tryWithGet :: Integer -> URL -> StatusCode -> Brok StatusCode
tryWithGet delay url (Right code)
| code >= 400 = makeRequest delay "GET" url
| otherwise = return (Right code)
tryWithGet delay url (Left (HttpExceptionRequest _ (InternalException _))) =
makeRequest delay "GET" url
tryWithGet delay url (Left _) = makeRequest delay "GET" url
fetch :: Integer -> URL -> Brok StatusCode
fetch delay url =
replace ("Fetching: " ++ url) >> makeRequest delay "HEAD" url >>= tryWithGet delay url
codeToResponse :: Link -> StatusCode -> Link
codeToResponse lnk (Right code)
| code >= 200 && code < 300 = working lnk code
| otherwise = broken lnk code
codeToResponse lnk (Left (HttpExceptionRequest _ _)) = failure lnk
codeToResponse lnk (Left (InvalidUrlException _ _)) = invalid lnk
check :: Integer -> Link -> Brok Link
check delay lnk = codeToResponse lnk <$> fetch delay (getURL lnk)