Tue Dec 11
Your task for this assignment is to complete a tiny web application that has two pages: the index (aka home) at /
, and an “about” page at /about
. There should by hyperlinks between the two pages. It should return a 404 status and “not found” error message if any pages besides these two are accessed. Below is a starting point.
To get this to work on the Mimir IDE, you will need these packages:
apt install ghc libghc-warp-dev libghc-blaze-html-dev
You can run it from the Linux command-line:
% PORT=80 runhaskell A11.hs
Listening...
Or from within ghci:
% ghci
GHCi, version 7.10.3: http://www.haskell.org/ghc/ :? for help
Prelude> :load A11.lhs
[1 of 1] Compiling A11Sol ( A11.lhs, interpreted )
Ok, modules loaded: A11Sol.
*A11Sol> startServer
Listening...
Once the program is listening for connections, select View » View Port » Port 80 from the menu in the IDE to see the site.
import Data.Monoid ((<>))
import Network.HTTP.Types.Header
import Network.HTTP.Types.Status
import Network.Wai as Wai
import System.Random (randomIO)
import Text.Blaze.Html.Renderer.Utf8 (renderHtml)
import Text.Blaze.Html5 as H hiding (main)
import Text.Blaze.Html5.Attributes as A
import qualified Data.ByteString.Char8 as BS
import qualified Data.Text as T
import qualified Data.Text.Encoding as TE
import qualified Network.Wai.Handler.Warp as Warp
To determine what page is being requested, apply Wai.pathInfo
to the req
object given to the app. It returns a list of text strings:
λ> :t Wai.pathInfo
Wai.pathInfo :: Request -> [T.Text]
It’s a list because each slash-separated component of the path in the URL becomes a separate item in the list. For example, accessing:
/
(the home page) produces the empty list []
/about
produces ["about"]
/user/13579/profile
produces ["user", "13579", "profile"]
You can use a case
statement to pattern-match on the list returned by Wai.pathInfo
.
myPage :: String -> Int -> Html
myPage name num = docTypeHtml $ do
h1 "My home page"
p $ do
"Hello "
b ! A.style "color:#9a1a33" $ toHtml name
p $ do
"My favorite number is "
toHtml num
p $ do
a ! href "/about" $ "About me"
app :: Wai.Application
app req respond = do
BS.putStrLn $ Wai.requestMethod req <> " " <> Wai.rawPathInfo req
num <- randomIO
respond $ responseLBS ok200 [("Content-Type","text/html")]
$ renderHtml $ myPage "Chris" num