--- title: Spock - Hello World description: A bare-minimum web application using Spock date: 2017-11-24 --- This literate haskell file demonstrates the most basic web application you can write with Spock. A copy of this runnable file is available [here](/static/SpockHello.lhs). You may run it via [stack](https://haskell-lang.org/get-started) with the following command: ``` stack --resolver lts-9.14 runghc --package Spock SpockHello.lhs ``` ---- Extensions --- >{-# LANGUAGE OverloadedStrings #-} Imports --- >import Web.Spock > ( SpockM > , runSpock > , spock > , get > , root > , text > ) | -----------|--------------------------------------------------------------------- `SpockM` |type alias to Spock's route definition monad `runSpock` | runs a Spock app `spock` | builds a runnable Spock app given a config and the app definition `get` | builds a route handler for HTTP GETs `root` | alias for the root route - i.e. "/" `text` | sends text as the response body. Content-Type is set to "text/plain" >import Web.Spock.Config > ( PoolOrConn(PCNoDatabase) > , defaultSpockCfg > ) | ---------------------|--------------------------------------------------------------------------------- `PoolOrConn` | sum type that we can utilize to let Spock manage database connections `PCNoDatabase` | value that lets Spock know that we do not intend for it to manage DB connections `defaultSpockCfg` | function that builds a Spock config with some default values Data types --- >data AppSession = EmptySession >data AppState = EmptyState AppSession represents the data that we wish to persist across a session. e.g. whether a user is signed in, their email address, basic profile info, etc. AppState represents the data that will be available to all our route handlers in Spock. e.g. configuration parameters set at application startup time - logging level, service locations, etc. These two data types both have a single empty constructor for now since we will not be making use of Sessions or State. Web application definition --- >webapp :: SpockM () AppSession AppState () >webapp = do > get root (text "Hello stranger!") Note the first and last type parameters to `SpockM` — the first parameter is the type of database pool/connection, which in our case is `()` since we told Spock that we do not wish for it to manage any such resource. The last parameter is the return type of our web application, which is `()` since we do not expect our web application to end. Our webapp consists of a single route: `GET /` returns "Hello stranger". Try it out by visiting http://localhost:5000/ Main --- >main :: IO () >main = do > defConfig <- defaultSpockCfg EmptySession PCNoDatabase EmptyState > runSpock 5000 (spock defConfig webapp) We build the default Spock configuration by passing 3 values to the function `defaultSpockCfg` — the initial session value, database pool/connection management value, and initial app state. Finally, we assemble the web application via `spock config webapp` and tell Spock to run it on port 5000. Note: By default, Spock listens on all interfaces. Exercises --- 1. (Easy) Add a route to `webapp` that handles `GET /ohai` and responds with the text "O hai!" 2. (Medium) Add a route to `webapp` that handles `POST /ohai` and responds with the text "O hai postie!" - You can test this via `curl -X POST http://localhost:5000/ohai`