Last active
December 19, 2015 17:09
-
-
Save jferris/5989476 to your computer and use it in GitHub Desktop.
Find URLs that redirect in stdin and replace them with their target URL in stdout
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import Control.Applicative | |
| import Data.List.Utils | |
| import Data.Maybe | |
| import Network.HTTP | |
| import Network.HTTP.Headers | |
| import System.IO | |
| import Text.Regex.PCRE | |
| main = do | |
| line <- getLine | |
| replacedLine <- replaceRedirects line | |
| putStrLn replacedLine | |
| eof <- isEOF | |
| if eof then return () else main | |
| replaceRedirects :: String -> IO String | |
| replaceRedirects line = foldl replaceRedirect (pure line) $ matchUrls line | |
| replaceRedirect :: IO String -> String -> IO String | |
| replaceRedirect line url = | |
| replace <$> pure url <*> targetUrlFromUrl url <*> line | |
| targetUrlFromUrl :: String -> IO String | |
| targetUrlFromUrl sourceUrl = | |
| simpleHTTP (getRequest sourceUrl) >>= | |
| return . either (\_ -> sourceUrl) targetUrl | |
| where targetUrl = fromMaybe sourceUrl . findHeader HdrLocation | |
| matchUrls :: String -> [String] | |
| matchUrls line = map head $ line =~ "http://[^ ]+" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Cool!
To address the
mainfunction, I would just write something like this:The other thing I noticed is that you've got a lot of
IOgoing far into the logic of the program. Ideally, theIOshould occur at only the top level of the program, with the major logic occurring in pure functions. All the Applicative hoops you have to jump through might be an indication something's amiss there.One way I think you can get to that point would be to make the GET requests and build up a "TODO" of replacements in the same general area you have to do the IO of reading and printing. Then the machinery of making those replacements can be pure functions.
My attempt to go that direction turned out like this:
I dunno, my 2c anyway.