Yesod (web framework)
The topic of this article may not meet Wikipedia's general notability guideline. (October 2012) |
Original author(s) | Michael Snoyman |
---|---|
Developer(s) | Michael Snoyman et al. |
Initial release | 2010 |
Stable release | 1.1.3[1]
/ September 26, 2012 |
Repository | |
Written in | Haskell |
Operating system | Cross-platform |
Available in | Haskell |
Type | Web application framework |
License | MIT |
Website | yesodweb |
Yesod, a word that comes from the Hebrew language, with stress on sod, is a free web application framework based on Haskell for productive development of type-safe, RESTful, high performance web applications, developed by Michael Snoyman et al.
Yesod is based on templates, to generate data instances for several entities, and dynamic content process functions, making use of Haskell Quasiquotation[2] to check and compile the templates, making it fully statically typed.[3]
Controller
server interface
Yesod uses a Web application interface API[4], abbrev. wai, to isolate servlets, aka web apps., from servers, with handlers for CGI,[5] FastCGI,[6] SCGI,[7] Warp,[8] Launch (open as local URL to the default browser, closing the server when the window is closed),[9] ..
WAI CGI Hello World
{- file wai-cgi-hello.hs -}
{-# LANGUAGE PackageImports, OverloadedStrings #-}
import "wai" Network.Wai
import "http-types" Network.HTTP.Types.Status
import "wai-extra" Network.Wai.Handler.CGI (run) -- interchangeable WAI handler
import "conduit" Data.Conduit (ResourceT)
import "bytestring" Data.ByteString.Lazy (fromChunks)
import qualified "text" Data.Text.Encoding as TE
-- wai type Application = Request -> ResourceT IO Response
myapp :: Application
myapp req = do
-- LBS is for lazy ByteString
return $ responseLBS ok200 [("Content-type", "text/plain")] content
where
content = fromChunks [TE.encodeUtf8 "Hello World\n"]
main = run myapp
export REMOTE_ADDR=127.0.0.1
export REQUEST_METHOD=GET
export PATH_INFO=/
./wai-cgi-hello
Resources, Routes and HTTP method handlers
Yesod follows the REpresentational State Transfer model of access to web documents, identifying docs. and directories as resources, named with an uppercase R suffix (for example, HomeR).
The parseRoutes template should list the resources specifying route pieces, resource name and dispatch methods.[10]
[parseRoutes| / HomeR GET POST /article/#ArticleId ArticleR GET PUT |]
For every dispatch method a handler function must be created by prefixing the method name to the resource, to match the generated dispatch names, as described:
-- / HomeR GET POST
getHomeR :: Handler RepHtml
postHomeR :: Handler RepHtml
-- /article/#ArticleId ArticleR GET PUT
getArticleR :: ArticleId -> Handler RepHtml
putArticleR :: ArticleId -> Handler RepHtml
Model
- persistent is the name of the database access layer with templates for generating an entity type for each table.[11][12]
There is first class support for PostgreSQL, SQLite and MongoDB, with experimental support for CouchDB and MySQL.[11]
[persist| User -- table name and entity record type -- implied autoincrement column "id" as primary key, typed UserId ident Text -- record field "userIdent" (prefixing the entity name) password Text Maybe -- Maybe: Nullable field UniqueUser ident -- unique constraint with comma sep. field list Email email Text user UserId -- foreign key verkey Text Maybe UniqueEmail email |]
- Esqueleto: is a haskell combinators layer to generate correct relational queries to persistent.[13]
Persistent rawSQL and Esqueleto query example.[14]
Forms
There are Applicative, Monadic and Input (non rendering, input only) kinds of forms. [15]
View
Content is defined in composable yesod widgets[16] which are code elements that can be generated from html/javascript/css w3c doc. pieces, and combined within a WriterT monad transformer.[17]
shakespearean templates
See ref.[18] These are content view templates that follow a common substitution pattern to refer to
- other templates of the same type as ^{template_expression},
- safe urls as @{route_expression},
- haskell expression rendering as #{showable_haskell_expression}
- i18n message rendering _{MsgMessage params}
localizable (i18n) messages
See ref.[19] For every supported language ISO name there should be a file in the messages subfolder as en.msg with entries as
ArticleUnexistant id@Int64: unexistant article #{id}
each one of them generates a msg constructor prefixed by "Msg", so the example msg. can be referred as
-- in code myMsg = MsgArticleUnexistant myArticleId -- in templates _{MsgArticleUnexistant myArticleId}
HTML Templates
- hamlet templates.[20]
toWidget [hamlet| $doctype 5 <html> <head> <title>#{pageTitle} - My Site <link rel=stylesheet href=@{Stylesheet_route}> <body> <div> ^{headerTemplate} <div> <p>_{MsgArticleListTitle} $if null articles <p>_{MsgEmptyList} $else <ul> $forall art <- articles <li>#{articleNumber art} .- #{articleTitle art} <div> ^{footerHamletTemplate} |]
Javascript Templates
- julius: a javascript template.[21]
toWidgetHead [julius| var myfunc = function(){document.location = "@{SomeRouteR}";} ^{extraJuliusTemplate} |]
CSS Templates
- lucius: a css template with standard syntax plus shakespeare-template style substitutions.[22]
toWidgetHead [lucius| .box { border: 1px solid #{myColor} ; background-image: url(@{MyImageR}) ; } ^{extraLuciusTemplate} |]
- cassius: a css template with indentation based structuring.[22]
toWidget [cassius| .box border: 1px solid #{myColor} background-image: url(@{MyImageR}) ^{extraCassiusTemplate} |]
Getting started
Create a sandboxed cabal-dev repository for yesod and yesod projects.
mkdir yesod && cd yesod cabal-dev install yesod export PATH=$PWD/cabal-dev/bin:$PATH
Scaffolding
The console command yesod init
after asking for details, generates a starting scaffold application in a subfolder with the project name. Then cd to the project folder.
Create a link to the parent dir. cabal-dev folder (if you want to use the same library repository) and build the project
ln -s ../cabal-dev cabal-dev cabal-dev install
Configuration environments
- Development, Testing, Staging, Production
You may launch your server project with one of theese environments described as configuration property sets in the config files settings.yml and <yourDBMS>.yml that permit specifying different base url as approot, port, and other config. as well as different database names, and other db parameters adjustable for the purposes of the specific environment.
You have to add the preferred config. environment as argument to your project task.
# launch the server with the ''Testing'' configuration environment. # cabal-dev installs executables at ./cabal-dev/bin my_project Testing
Developing
The console command yesod --dev devel
(the --dev
flag is to look for cabal-dev library repo.) compiles the project in the current folder and starts it as a web server, but also listens for file modifications in the project directory tree, and recompiles it every time you save a yesod component, whether haskell code or template file.
Deploying
See ref.[23] There is somewhat automatic deploy handling for the Nginx web server through a yesod server daemon process called keter.[24]
>> Keter handles deployment of web apps, providing a reverse proxy to achieve zero downtime deployments.[25]
The console command yesod keter
packs the web app. project for uploading. A keter process monitors an incoming folder and deploys the web app. in a similar way as the Tomcat Java server deploys servlets.
With Apache it can be run as a reverse proxy as Warp or as a FastCGI/CGI Apache handler.
References
- ^ The yesod-platform package
- ^ HaskellWiki - QuasiQuotation
- ^ Univ. of Kent - Comparing Dynamic and Static Language Approaches to Web Frameworks - Yesod vs Ruby on Rails
- ^ The wai package
- ^ The wai-extra package with CGI WAI handler
- ^ The wai-handler-fastcgi package
- ^ The wai-handler-scgi package
- ^ The warp package
- ^ The wai-handler-launch package
- ^ book - Routing and Handlers
- ^ a b book - Persistent
- ^ Yesod-persistent package
- ^ esqueleto package
- ^ Query example at StackOverflow.com
- ^ book - Forms
- ^ book - Widgets
- ^ The widget monad
- ^ book - Shakesperean templates
- ^ book - Internationalization
- ^ The hamlet package
- ^ The shakespeare-js package
- ^ a b Package shakespeare-css
- ^ book - Deploying your Webapp
- ^ Yesod keter
- ^ The keter package
External links
- Yesod home page
- InfoQ - Yesod presentation
- Haskell eXchange 2012: Blake Rain on Scalable web applications with Yesod
- FP Complete - Yesod tutorial
- Yesod tutorial for newbies
- O'Reilly ebook - Developing Web Applications with Haskell and Yesod - Safety-Driven Web Development
- HaskellWiki - Haskell web frameworks
- A Hopefully Fair and Useful Comparison of Haskell Web Frameworks