Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

calling network IO from within haskeline

I have an existing program which takes command line arguments (username, password, date) and then uses the Network.HTTP.Conduit library to post an xml message to a server. I then parse the results, do some work and use blaze-html to write out to a file.

It all works like a charm; however, I thought I'd use haskeline so that the password isn't visible. I'm able to create a command line program that gets the user-supplied values and prints them out, but if I call the function that uses conduit, it never returns.

Here is the offending code:

main = runInputT defaultSettings loop
where 
    loop :: InputT IO ()
    loop = do
        Just username <- getInputLine "WM username: "
        Just password <- getPassword (Just '*') "WM password: "
        Just date     <- getInputLine "Date (YYYYMMDD): "

        outputStrLn "querying WM..."
        clients <- lift $ getWMClients username password
        outputStrLn "successfully retrieved client list from WM..."

        let outHeader = renderHeader date username

        reportString <- mapM  (\x -> createString x clients)  cList

        lift $ writeFile (date ++ "_report.html") (outHeader ++ concat reportString)
        outputStrLn "Done"

The function getWMClients function is:

getWMClients :: Username -> String -> IO [Client]
getWMClients username password = do
    let f = [Size "-1", Skip "0"]
    let fs = [Select "id",
              Select "status",
              Select "last-name",
              Select "first-name",
             ]
    let query = WMQuery {transaction=SHARE,service=Query,businessObject=CONT,field=f,fields=fs}

    results <- doQuery username (Just password) Nothing (Just query)
    rows <- xmlResultsToMaps results

    let clients = map makeClient rows
    return clients

When I run the program it hangs at "querying WM..." I don't think http-conduit is ever actually running. Any hints on how to make this work?

Thanks in advance, Neil

like image 407
Neil Avatar asked Nov 13 '22 04:11

Neil


1 Answers

You claim it worked with hard-coded username, password, date before haskeline. To help debug, perhaps you could not lift the conduit into InputT. Does the following still fail? (I did not compile this, so feel free to fix the syntax errors...)

-- Isolate the haskeline monad to just the input part:
main = loop
where 
    loop :: IO ()
    loop = do
      (username,password,date) <- runInputT defaultSettings $ do
        Just username <- getInputLine "WM username: "
        Just password <- getPassword (Just '*') "WM password: "
        Just date     <- getInputLine "Date (YYYYMMDD): "
        return (username,password,date)

      putStrLn "querying WM..."
      clients <- getWMClients username password
      putStrLn "successfully retrieved client list from WM..."

      let outHeader = renderHeader date username

      putString <- mapM  (\x -> createString x clients)  cList

      writeFile (date ++ "_report.html") (outHeader ++ concat reportString)
      putStrLn "Done"
like image 61
Chris Kuklewicz Avatar answered Dec 31 '22 05:12

Chris Kuklewicz