@@ -6,12 +6,15 @@ module Hakyll.Check
7--------------------------------------------------------------------------------
7--------------------------------------------------------------------------------
8import Control.Applicative ((<$>))
8import Control.Applicative ((<$>))
9+import Control.Exception (SomeException, handle)
9import Control.Monad (forM_)
10import Control.Monad (forM_)
10import Control.Monad.Reader (ReaderT, ask, runReaderT)
11import Control.Monad.Reader (ReaderT, ask, runReaderT)
11import Control.Monad.Trans (liftIO)
12import Control.Monad.Trans (liftIO)
12import Control.Monad.Writer (WriterT, runWriterT, tell)
13import Control.Monad.Writer (WriterT, runWriterT, tell)
13import Data.List (isPrefixOf)
14import Data.List (isPrefixOf)
14import Data.Monoid (Monoid (..))
15import Data.Monoid (Monoid (..))
16+import qualified Network.HTTP.Conduit as Http
17+import qualified Network.HTTP.Types as Http
15import System.Directory (doesDirectoryExist, doesFileExist)
18import System.Directory (doesDirectoryExist, doesFileExist)
16import System.FilePath (takeDirectory, takeExtension, (</>))
19import System.FilePath (takeDirectory, takeExtension, (</>))
17import qualified Text.HTML.TagSoup as TS
20import qualified Text.HTML.TagSoup as TS
@@ -89,14 +92,25 @@ checkFile filePath = do
89 else checkInternalUrl filePath url
92 else checkInternalUrl filePath url
95+--------------------------------------------------------------------------------
96+ok :: String -> Checker ()
97+ok _ = tell $ mempty {checkerOk = 1}
100+--------------------------------------------------------------------------------
101+faulty :: String -> Checker ()
103+ logger <- checkerLogger <$> ask
104+ Logger.error logger $ "Broken link to " ++ show url
105+ tell $ mempty {checkerFaulty = 1}
92--------------------------------------------------------------------------------
108--------------------------------------------------------------------------------
93checkInternalUrl :: FilePath -> String -> Checker ()
109checkInternalUrl :: FilePath -> String -> Checker ()
94checkInternalUrl base url = case url' of
110checkInternalUrl base url = case url' of
95− "" -> tell $ mempty {checkerOk = 1}
111+ "" -> ok url
97− logger <- checkerLogger <$> ask
98 config <- checkerConfig <$> ask
113 config <- checkerConfig <$> ask
100 let dest = destinationDirectory config
114 let dest = destinationDirectory config
101 dir = takeDirectory base
115 dir = takeDirectory base
@@ -104,11 +118,7 @@ checkInternalUrl base url = case url' of
104 | otherwise = dir </> url'
118 | otherwise = dir </> url'
106 exists <- checkFileExists filePath
120 exists <- checkFileExists filePath
107− if exists
121+ if exists then ok url else faulty url
108− then tell $ mempty {checkerOk = 1}
110− tell $ mempty {checkerFaulty = 1}
111− Logger.error logger $ base ++ ": broken link to " ++ show url
113 url' = stripFragments url
123 url' = stripFragments url
@@ -118,7 +128,22 @@ checkExternalUrl :: String -> Checker ()
118checkExternalUrl url = do
128checkExternalUrl url = do
119 logger <- checkerLogger <$> ask
129 logger <- checkerLogger <$> ask
120 Logger.message logger $ "Not checking external url " ++ url
130 Logger.message logger $ "Not checking external url " ++ url
121− -- TODO: use http-conduit and a cache?
131+
132+ isOk <- liftIO $ handle failure $ Http.withManager $ \manager -> do
133+ request <- Http.parseUrl url
134+ response <- Http.http (settings request) manager
135+ let code = Http.statusCode (Http.responseStatus response)
136+ return $ code >= 200 && code < 300
138+ if isOk then ok url else faulty url
141+ { Http.redirectCount = 10
142+ , Http.responseTimeout = Just 10
145+ failure :: SomeException -> IO Bool
146+ failure e = print e >> return False
124--------------------------------------------------------------------------------
149--------------------------------------------------------------------------------