Skip to content

Instantly share code, notes, and snippets.

@hardentoo
Created June 11, 2018 21:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hardentoo/c5892d57db028bc71fe0f1638bd0a26f to your computer and use it in GitHub Desktop.
Save hardentoo/c5892d57db028bc71fe0f1638bd0a26f to your computer and use it in GitHub Desktop.
A simple wget style program using Haskell and http-enumerator
{-# LANGUAGE OverloadedStrings #-}
import Control.Monad.IO.Class (liftIO)
import Network (withSocketsDo)
import System.Environment (getArgs, getProgName)
import qualified Data.ByteString.Char8 as BS
import qualified Data.ByteString.Lazy.Char8 as LBS
import qualified Data.CaseInsensitive as CI
import qualified Network.HTTP.Enumerator as HE
import qualified Network.HTTP.Types as HT
main :: IO ()
main
= do args <- getArgs
name <- getProgName
case args of
[url] -> withSocketsDo $ grabUrl url
_ -> error $ "Usage: " ++ name ++ " <url>"
grabUrl :: String -> IO ()
grabUrl url
= do let request = mkRequest url
HE.Response sc rh bs <- liftIO $ HE.withManager $ HE.httpLbsRedirect request
if sc /= 200
then error $ "Http error : " ++ show sc
else writeResponse sc rh bs
mkRequest :: String -> HE.Request m
mkRequest url
= case HE.parseUrl url of
Nothing -> error $ "Failed to parse target url '" ++ url ++ "'."
Just r -> r { HE.rawBody = True }
writeResponse :: Int -> HT.ResponseHeaders -> LBS.ByteString -> IO ()
writeResponse sc rh bs
= do let fname = "he-get.output"
LBS.writeFile fname
$ LBS.unlines
$ LBS.concat [ "HTTP/1.0 ", LBS.pack (show sc) ]
: LBS.fromChunks (map (\ (f, v) -> BS.concat [ CI.original f, ": ", v, "\n" ]) rh)
: LBS.pack ""
: [ bs ]
putStrLn $ "Output written to '" ++ fname ++ "'."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment