Reputation: 1861
I am following the basic dispatching section of wai application.
I am able to catch the url parameter. How can I perform IO operation using these params.
I would like to use runCommand
of System.Process to execute a system command using these parameters.
:t runCommand give
runCommand :: String -> IO ProcessHandle
my Main.hs
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Control.Monad
import Network.Wai
import Network.HTTP.Types
import Network.Wai.Handler.Warp (run)
import Data.ByteString
import Control.Monad
import System.Process
import qualified Data.ByteString.Lazy.Char8 as L8
main :: IO ()
main = do
run 8080 app
app :: Application
app request respond = respond $ case rawPathInfo request of
"/" -> indexHtml
"/wake" -> wakeMeUP request
_ -> fourNotFour
indexHtml :: Response
indexHtml = responseFile
status200
[("Content-Type","text/html")]
"index.html"
Nothing
wakeMeUP :: Request -> Response
wakeMeUP request =
let query = queryString request
hour = join $ lookup "hour" query
min = join $ lookup "min" query
--I would like to use runCommand "using hour and min variables"
in responseLBS
status200
[("Content-Type","text/plain")]
"Alarm set at...to be coded later"
fourNotFour :: Response
fourNotFour = responseLBS
status404
[("Content-Type","text/plain")]
"404 not found"
Upvotes: 1
Views: 383
Reputation: 60513
Your design prevents it, because of how you have written app
,
app request respond = respond $ case rawPathInfo request of
which says that you immediately respond. Note the type of Application
:
type Application = Request -> (Response -> IO ResponseReceived) -> IO ResponseReceived
Since the result type has an IO
, you have the opportunity to do I/O before yielding a value. So you could:
app request respond = do
whateverResult <- runCommand "whatever"
respond $ ...
(You could also do it afterward, at least according to the types:
app request respond = do
rcvd <- respond $ ...
runCommand "whatever"
return rcvd
Though that's a bit odd to do for the continuation-passing idiom being used here (the (a -> b) -> b
pattern in the Application
type). It means that the command will be run after everything else, for some definition of "everything else" that we can't know without reading the wai
source.)
Anyway, you probably don't want the command to be run inside app
, but rather in wakeMeUp
, which means you need to change some types around. In particular,
wakeMeUp :: Request -> IO Response
-- ^^
and suitably monadify the function. Then your app
needs to not call respond
immediately, so you can say
app request respond =
response <- case rawPathInfo request of
"/" -> return indexHtml
-- ^^^^^^
"/wake" -> wakeMeUp request
-- no change, because wakeMeUp now has an IO return type
...
respond response
If this is gibberish to you, it's time to do some monad tutorials. Or if you just want to get the damn thing working, I recommend Dan Piponi's The IO Monad For People who Simply Don't Care. Happy hacking!
Upvotes: 1