File: README.md

package info (click to toggle)
haskell-wai 3.2.4-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 104 kB
  • sloc: haskell: 336; makefile: 3
file content (116 lines) | stat: -rw-r--r-- 2,780 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
WAI: Web Application Interface
==============================

Getting started
---------------

You want a minimal example? Here it is!

~~~ {.haskell}
{-# LANGUAGE OverloadedStrings #-}
import Network.Wai
import Network.HTTP.Types
import Network.Wai.Handler.Warp (run)

app :: Application
app _ respond = do
    putStrLn "I've done some IO here"
    respond $ responseLBS
        status200
        [("Content-Type", "text/plain")]
        "Hello, Web!"

main :: IO ()
main = do
    putStrLn $ "http://localhost:8080/"
    run 8080 app
~~~

Put that code into a file named _hello.hs_ and install [wai] and [warp] from Hackage:

    cabal install wai warp

Run it:

    runhaskell hello.hs

Point your browser to:

    http://localhost:8080/


Serving static content
----------------------

We can modify our previous example to serve static content. For this create a file named _index.html_:

    <p>Hello, Web!</p>

Now we redefine `responseBody` to refer to that file:

~~~ {.haskell}
app2 :: Application
app2 _ respond = respond index

index :: Response
index = responseFile
    status200
    [("Content-Type", "text/html")]
    "index.html"
    Nothing
~~~


Basic dispatching
-----------------

An `Application` maps `Request`s to `Response`s:

    ghci> :info  Application
    type Application = Request -> (Response -> IO ResponseReceived) -> IO ResponseReceived

Depending on the path info provided with each `Request` we can serve different `Response`s:

~~~ {.haskell}
app3 :: Application
app3 request respond = respond $ case rawPathInfo request of
    "/"     -> index
    "/raw/" -> plainIndex
    _       -> notFound

plainIndex :: Response
plainIndex = responseFile
    status200
    [("Content-Type", "text/plain")]
    "index.html"
    Nothing

notFound :: Response
notFound = responseLBS
    status404
    [("Content-Type", "text/plain")]
    "404 - Not Found"
~~~


Doing without overloaded strings
--------------------------------

For the sake of efficiency, WAI uses the [bytestring] package.  We used GHCs [overloaded strings] to almost hide this fact. But we can easily do without.  What follows is a more verbose definition of `notFound`, that works without GHC extensions:

~~~ {.haskell .ignore}
import qualified Data.ByteString.Char8 as B8
import qualified Data.ByteString.Lazy.Char8 as LB8
import           Data.CaseInsensitive (mk)

notFound = responseLBS
    status404
    [(mk $ B8.pack "Content-Type", B8.pack "text/plain")]
    (LB8.pack "404 - Not Found")
~~~


 [wai]: http://hackage.haskell.org/package/wai
 [warp]: http://hackage.haskell.org/package/warp
 [overloaded strings]: http://www.haskell.org/ghc/docs/latest/html/users_guide/type-class-extensions.html#overloaded-strings
 [bytestring]: http://hackage.haskell.org/package/bytestring