[updates to HelloWorld.lhs Jeremy Shaw **20100413201817 Ignore-this: 74cdcaaaf1a4f719158584e79f280463 ] hunk ./HelloWorld.lhs 1 + + hunk ./HelloWorld.lhs 17 -> main = simpleHTTP nullConf $ ok (toResponse "Hello, World!") +> main = simpleHTTP nullConf $ ok "Hello, World!" hunk ./HelloWorld.lhs 50 +

The top-level function simpleHTTP is what actually starts the programming listening for incoming HTTP requests.

+ hunk ./HelloWorld.lhs 55 + +

The first argument is some simple server configuration information. It is defined as:

+ +#ifdef HsColour +> data Conf = Conf { port :: Int +> , validator :: Maybe (Response -> IO Response) +> } +#endif + +

The port is the TCP port to listen on for incoming connection. The validator is used to do on-the-fly validation of output during development. It's will eventually be described elsewhere is this document.

+ +

The default config is nullConf which is simply defined as:

+ +#ifdef HsColour +> -- | Default configuration contains no validator and the port is set to 8000 +> nullConf :: Conf +> nullConf = Conf { port = 8000 +> , validator = Nothing +> } +#endif + +

The second argument is a bit more interesting. The ServerPartT IO a is the code that actually processes an incoming HTTP Request and generates a Response. The ServerPartT IO monad is essentially a fancy way of writing a function with the type:

+ +#ifdef HsColour +> Request -> IO Response +#endif + +

simpleHTTP processes each incoming request in it's own thread. It will parse the Request call your ServerPartT handler, and then return the Response to the client. When developing your server part, it is natural to think about things as if you are writing a program which processes a single Request, generates a Response, and exits. However it is important when doing I/O, such as writing files to disk, or talking to a ''database'' to remember that there may be other threads running simultaneously.

+ + +

In this example, our server part is simply:

+ +#ifdef HsColour +> ok "Hello, World!" +#endif + +

ok is one of several combinators which can be used to set the HTTP response code. In this case, it will set the response code to 200 OK.

+ +

The body of the response will be "Hello, World!".

+ +

The String "Hello, World!" is turned into a Response because simpleHTTP calls toResponse from the ToMessage class on it. Often times we will opt to make this call explicit rather than implicit. For example:

+ +#ifdef HsColour +> main :: IO () +> main = simpleHTTP nullConf $ ok (toResponse "Hello, World!") +#endif + +

The toResponse function takes care of setting the Content-type and converting the value into a lazy ByteString which will be sent back to the client. Happstack comes with pre-defined ToMessage instances for many types such as Text.Html.Html, Text.XHtml.Html, String, the types from HSP, and more.

+ hunk ./Main.lhs 5 - Data Serialization, Deserialization, and Migration using HAppS-Data + Crash Course in Happstack hunk ./Makefile 55 - HsColour -css -partial $< -o$@ -lit + ./HsColour -css -partial $< -o$@ -lit hunk ./blog.css 4 - width: 40em; + width: 35em; hunk ./blog.css 24 +code +{ }