# Routing Fundamentals If you're familiar with other web frameworks, you will have a pretty good idea of the basic paradigm of URL routing, but for the uninitiated I will explain the basics here. When you visit your favorite website the first thing your browser will request from the server a specific resource. The very first line of the connection to the server will often look like this GET /blog/archive/2005/10/02 HTTP/1.1 The first part of the header, namely `GET` is known as the Method. Here' we're performing a simple GET request to retrieve the contents of the resource located at `/blog/archive/2005/10/02` and using the `HTTP/1.1` version of the protocol to do so. The location of the resource is known as Path which the framework maps to a Route. Many web frameworks present some programmable way to specify a link between routes and the specific function that they should run in order to serve that route. # Ruby (Using a DSL) match "/patients/:id" => "patients#show" # Flask (Using a DSL) @app.route('/patients/') def patients_detail(id): ... # Django (Using regex) url(r'^patients/(?P\d+)/$', views.PatientsDetailView.as_view()) When a request comes into the server, the framework interprets the path and maps it to the appropriate route and hands off control the the function associated with that URL. The result is a function called with string arguments. In yesod, the fundamental unit ``` haskell type PatientId = Int -- This is the URL routing definition mkYesod "BusinessDirectory" [parseRoutes| /patients/#PatientId PatientDetailR GET |] -- The views that can be called getPatientDetailR :: Handler RepHTML getPatientDetailR id = undefined ``` This defines a single route that takes a single parameter of type `PatientId` and can service the `GET` HTTP method. ``` active haskell web {-# LANGUAGE OverloadedStrings, FlexibleContexts, ScopedTypeVariables, GeneralizedNewtypeDeriving, TemplateHaskell, GADTs, TypeFamilies, QuasiQuotes, MultiParamTypeClasses #-} -- As usual, a generous helping of pragmas and imports. -- These will need to be placed at the top of your source files. -- Everything you need to work with Yesod, exported from one package import Yesod -- Standard platform datatypes & functions import Data.Text (Text) import Data.Time (UTCTime, getCurrentTime) import Data.Time.Format (formatTime) import System.Locale (defaultTimeLocale) -- Persist import Database.Persist import Database.Persist.Sqlite import Database.Persist.TH -- Monad helpers import Control.Applicative ((<$>),(<*>)) import Control.Monad.IO.Class (liftIO) import Control.Monad.Logger (runNoLoggingT) import Control.Monad.Trans.Resource (runResourceT) data BusinessDirectory = BusinessDirectory { _db :: Connection } instance Yesod BusinessDirectory instance YesodPersist BusinessDirectory where type YesodPersistBackend BusinessDirectory = SqlPersist runDB action = getYesod >>= runSqlConn action . _db share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persist| Business name String deriving Show Contact businessId BusinessId name String deriving Show |] mkYesod "BusinessDirectory" [parseRoutes| / HomeR GET /business/#BusinessId BusinessR GET /business/#BusinessId/contact/#ContactId ContactR GET |] blankR :: Handler RepHtml blankR = defaultLayout [whamlet|

This page intentionally left blank. |] getHomeR :: Handler RepHtml getHomeR = do businesses <- runDB $ selectList [] [Asc BusinessName] defaultLayout [whamlet|

Businesses