[Bring over the comments from the lhs file David Fox **20130624184836 Ignore-this: 9361bdf3962ccbb58b6af648ca0203a ] hunk ./Example.hs 14 +-- | To start the app we call the `serve` function. The first argument +-- is an optional configuration parameter. The second argument is our +-- web application: hunk ./Example.hs 20 +-- | The top-level of our application is just a bunch of routes mappings to handlers. +-- +-- `dir` is guard used to match on static path components. For +-- example, `dir "echo"`, will match on http://localhost:8000/echo. To +-- match on `"/foo/bar"` you would write, `dir "foo" $ dir "bar" $ +-- handler`. +-- +-- Each of the routes is tried until one successfully returns a +-- value. In this case, a `Response`. +-- +-- We convert the list of handlers in a single handler using `msum`. +-- +-- The last handler, `homePage` is not guarded by anything, so it will +-- always be called if none of the other handlers were successful. + hunk ./Example.hs 46 +-- | Since this is a web application, we are going to want to create +-- some HTML pages. We will do that using blaze-html. A blaze tutorial +-- can be found here: +-- +-- http://jaspervdj.be/blaze/tutorial.html +-- +-- I like to make a template function which captures common elements +-- of pages in my web app, such as importing style sheets, external +-- javascript files, menus, etc. For this tutorial we have a very +-- simple template: hunk ./Example.hs 65 +-- | `ok` tells the server to return the page with the HTTP response +-- code '200 OK'. There are other helper functions like `notFound` and +-- `seeOther` for other response codes. Or use `setResponseCode` to +-- specify a response code by number. hunk ./Example.hs 82 +-- | The `dir` function only matches on static path segments. If we have +-- a dynamic path segment, we can use the `path` function to capture +-- the value and optionally convert it to another type such as +-- Integer. In this example we just echo the captured path segment in +-- the html. For example, trying visiting: +-- +-- http://localhost:8000/echo/fantastic hunk ./Example.hs 96 +-- We can also extract values from the query string part of the URL. The +-- query string is the part that looks like "?foo=bar". Trying visiting: +-- +-- http://localhost:8000/query?foo=bar +-- +-- `lookText` will normally fail (by calling `mzero`) if the parameter +-- is not found. In this example we used `optional` from +-- `Control.Applicative` so that it will return a `Maybe` value +-- instead. hunk ./Example.hs 112 +-- | We can use `lookText` (and friends) to extract values from forms +-- as well. +-- +-- We use the same `lookText` function from the previous section to +-- look up values in in form data. +-- +-- You will also note that we use the `method` function to select +-- between a `GET` request and a `POST` request. +-- +-- When the user first views the form, the browser will request +-- "/form" using the `GET` method. In the form tag, we see that the +-- form will also be submitted to "/form" when the user presses the +-- submit button. But in the form tag we have set the method attribute +-- to `POST`. hunk ./Example.hs 146 +-- | This example extends the form example to save the message in a +-- cookie. That means you can navigate away from the page and when you +-- come back later it will remember the message you saved. +-- +-- There are only a few new things in this example compared to the form example. +-- +-- 1. `lookCookieValue` works just like `lookText`, except it looks +-- for the value in the cookies instead of request paramaters or form +-- data. +-- +-- 2. `addCookies` sends cookies to the browser. addCookies has the +-- type: `addCookies :: [(CookieLife, Cookie)] -> ServerPart ()` +-- +-- 3. `CookieLife` specifies how long the cookie is valid. `Session` +-- means it is only valid until the browser window is closed. +-- +-- 4. `mkCookie` takes the cookie name and the cookie value and makes +-- a `Cookie`. +-- +-- 5. `seeOther` (aka, 303 redirect) tells the browser to do a new +-- GET request on "/fortune". hunk ./Example.hs 190 +-- | In most web applications, we will want to serve static files from the +-- disk such as images, stylesheets, javascript, etc. We can do +-- that using the `serveDirectory` function. +-- +-- The first argument specifies whether `serveDirectory` should create +-- directory listings or not. +-- +-- The second argument is a list of index files. If the user requests +-- a directory and the directory contains a index file (in this +-- example "index.html"), then the server will display that index file +-- instead of a directory listing. +-- +-- The third argument is the path to the directory we want to serve +-- files from. Here we serve files from the current directory. +-- +-- On support platforms (Linux, OS X, Windows), the `serveDirectory` +-- function will automatically use sendfile() to serve the +-- files. sendfile() uses low-level kernel operations to transfer +-- files directly from the disk to the network with minimal CPU usage +-- and maximal bandwidth usage. hunk ./Example.hs 214 +-- | Handling file uploads is very straight forward. We create a form, +-- just as before. Except instead of `lookText` we use `lookFile`. +-- +-- When a file is uploaded, we store it in a temporary location. The +-- temporary file will automatically be deleted after the server has +-- sent the response. That ensures that unused files don't clutter up +-- the disk. +-- +-- In most cases, you don't want a user to upload a file just to have +-- it deleted. Normally the upload handler would use `moveFile` or +-- `copyFile` to move (or copy) the temporary file to a permanent +-- location.