joncfoo

Spock - Path Parameters

Posted on 2017-11-24

This literate haskell file demonstrates how to use path parameters with Spock. A copy of this runnable file is available here. You may run it via stack with the following command:

stack --resolver lts-9.14 runghc --package Spock --package string-conv SpockPath.lhs

Extensions

{-# LANGUAGE OverloadedStrings #-}

Imports

import Data.Monoid ( (<>) )
import Data.String.Conv (toS)
import Web.Spock
    ( SpockM, runSpock, spock, get, text
    , (<//>)
    , var
    , static
    , wildcard
    )
toS seamlessly converts between String, Text, and ByteString values
<//> operator that combines two path components
var placeholder for a path parameter
static used to define a static path
wildcard matches the remaining part of the path
import Web.Spock.Config
    ( PoolOrConn ( PCNoDatabase )
    , defaultSpockCfg
    )

Data types

data AppSession = EmptySession
data AppState = EmptyState

Web application definition

webapp :: SpockM () AppSession AppState ()
webapp = do
   get ("hola" <//> var) $ \name -> do
       text ("Hola " <> name <> "!  ¿Qué pasó?")

The route above handles GET requests to /hola/<some-name>. <//> combined the path component "hola" and path placeholder component introduced by var.

Try visiting:

   get ("add" <//> var <//> "to" <//> var) $ \x y -> do
       text . toS . show $ (x + y :: Int)

Can you guess what the route above matches?

If you guessed /add/<x>/to/<y> you’re correct! As you can see var is used to introduce a placeholder in the path and <//> combines path pieces.

Try visiting:

   get (static "what-is-this") $ do
       text "just some text"

The route above is equivalent to having declared it like so: get "what-is-this" $ .... As you can tell, static is an alternative way to declare paths. You can learn more about why these are equivalent by completing Exercise 1.

   get ("gotta" <//> wildcard) $ \rest -> do
       text ("you have to: " <> rest)

wildcard is similar to var in that it is a placeholder. However, unlike var, it matches the rest of the path and only gives a Text parameter. Additionally, it must be the last component in the path specification.

Try visiting:

Main

main :: IO ()
main = do
    defConfig <- defaultSpockCfg EmptySession PCNoDatabase EmptyState
    runSpock 5000 (spock defConfig webapp)

Exercises

  1. (Medium) Investigate the instances of Path. How do you suppose Strings get converted to Paths?

  2. (Medium) Try to append a var to the wildcard example above. What happens? Why do you suppose this is the case?