Skip to main content

  | मौसम…

411 समाचार
Public archive edition · Attributed source reporting with original dates · AI drafts are excluded

411 REFERENCE · Wikibooks

Yesod web framework/Controller

Reference material by Wikibooks contributors. This retains its source identity and is not 411 news reporting.

Server interface Yesod uses a Web application interface API,http://hackage.haskell.org/package/wai The wai package Hackage.haskell.org 2012-10-23 abbreviated WAI, to isolate servlets, aka web apps., from servers, with handlers for the server protocols CGI,http://hackage.haskell.org/package/wai-extra The wai-extra package with CGI WAI handler Hackage.haskell.org 2012-10-23 FastCGI,http://hackage.haskell.org/package/wai-handler-fastcgi The wai-handler-fastcgi package Hackage.haskell.org 2012-10-23 SCGI,http://hackage.haskell.org/package/wai-handler-scgi The wai-handler-scgi package Hackage.haskell.org 2012-10-23 Warp,http://hackage.haskell.org/package/warp The warp package Hackage.haskell.org 2012-10-23 Launch (open as local URL to the default browser, closing the server when the window is closed),http://hackage.haskell.org/package/wai-handler-launch The wai-handler-launch package Hackage.haskell.org 2012-10-23 The foundation type See ref.http://www.yesodweb.com/book/basics book - Basics Yesodweb.com 2012-10-23 Yesod requires a data type that instantiates the controller classes. This is called the foundation type. In the example below, it is named "MyApp". The REST model identifies a web resource with a web path. Here REST resources are given names with an R suffix (like "HomeR") and are listed in a parseRoutes site map description template. From this list, route names and dispatch handler names are derived. Yesod makes use of Template Haskell metaprogramming to generate code from templates at compile time, assuring that the names in the templates match and everything typechecks (e.g. web resource names and handler names). By inserting a mkYesod call, this will call Template Haskell primitives to generate the codeThe mkYesod code corresponding to the route type members, and the instances of the dispatch controller classes as to dispatch GET calls to route HomeR to a routine named composing them both as "getHomeR", expecting an existing handler that matches the name. Hello World "Hello world" example based on a CGI server interface (The actual handler types have changed, but the philosophy remains): {- file wai-cgi-hello.hs -} {-# LANGUAGE PackageImports, TypeFamilies, QuasiQuotes, MultiParamTypeClasses, TemplateHaskell, OverloadedStrings #-} import "wai" Network.Wai import "wai-extra" Network.Wai.Handler.CGI (run) -- interchangeable WAI handler import "yesod" Yesod import "yesod-core" Yesod.Handler (getRequest) import "text" Data.Text (Text) import "shakespeare" Text.Cassius (Color(..), colorBlack) -- the Foundation type data MyApp = MyApp -- sitemap template, listing path, resource name and methods accepted -- `mkYesod` takes the foundation type name as param. for name composition of dispatch functions mkYesod "MyApp" [parseRoutes| / HomeR GET |] instance Yesod MyApp -- indentation structured CSS template myStyle :: [Text] → CssUrl url myStyle paramStyle = [cassius| .box border: 1px solid #{boxColor} |] where boxColor = case paramStyle of ["high-contrast"] → colorBlack _ → Color 0 0 255 -- indentation structured HTML template myHtml :: [(Text, Text)] → HtmlUrl url myHtml params = [hamlet| <!-- indentation, or lack of it, under starting tags or commands ('$' prefix) describe the content or sequence tree structure --> <!-- '.' or '#' prefixes in tags introduce css styled "class" or "id" attribute values --> <!-- interpolation of haskell expressions follow the "shakespeare templates" #{expr} syntax --> <p>Hello World! There are <span .box>#{length params} parameters</span>: $if null params <p>Nothing to list $else <ul> $forall param <- params <li>#{fst param}: #{snd param} |] getHomeR :: Handler RepHtml getHomeR = do req <- getRequest let params = reqGetParams req paramStyle <- lookupGetParams "style" defaultLayout $ do -- adding widgets to the Widget monad (a ''Writer'' monad) setTitle "Yesod example" toWidgetHead $ myStyle paramStyle toWidgetBody $ myHtml params -- there are ''run'' function variants for different WAI handlers main = toWaiApp MyApp >>= run # cgi test export REMOTE_ADDR=127.0.0.1 export REQUEST_METHOD=GET export PATH_INFO=/ export QUERY_STRING='p1=abc;p2=def;style=high-contrast' ./wai-cgi-hello Resources, routes and HTTP method handlers See ref.http://www.yesodweb.com/book/routing-and-handlers book - Routing and Handlers Yesodweb.com 2012-10-23http://fpcomplete.com/yesod-tutorial-2-playing-with-routes-and-links/ Playing with Routes and Links FPComplete.com 2012-10-17 2012-10-28 Yesod follows the REpresentational State Transfer model of access to web documents, identifying docs. and directories as resources with a Route constructor, named with an uppercase R suffix (for example, HomeR). The routes table The parseRoutes template should list the resources specifying route pieces, resource name and dispatch methods to be accepted. URL segment capture as parameter is possible specifying a '#' prefix for single segment capture or '*' for multisegment capture, followed by the parameter type. -- given a MyApp foundation type mkYesod "MyApp" [parseRoutes| / HomeR -- no http methods stated: all methods accepted /blog BlogR GET POST -- the '#' prefix specify the path segment as a route handler parameter /article/#ArticleId ArticleR GET PUT -- the '*' prefix specify the parameter as a sequence of path pieces /branch/*Texts BranchR GET -- to simplify the grammar, compound types must use an alias, eg. type Texts for ''[Text]'' |] Applying the previous template generates the following route constructors: data Route MyApp = HomeR -- referenced in templates as: @{HomeR} | BlogR -- in templates: @{BlogR} | ArticleR ArticleId -- in templates: @{ArticleR myArticleId} | BranchR Texts -- in templates: @{BranchR myBranchSegments} For every supported HTTP method a handler function must be created to match the dispatch names generated by mkYesod from the parseRoutes template, by prefixing the method name (or the prefix "handler" if no method stated) to the resource, as described (actual versions handler types have changed, but the philosophy remains): -- for "/ HomeR" -- no http methods stated ⇒ only one handler with prefix ''handler'' handlerHomeR :: HasReps t ⇒ Handler t -- for "/blog BlogR GET POST" getBlogR :: HasReps t ⇒ Handler t postBlogR :: HasReps t ⇒ Handler t -- for "/article/#ArticleId ArticleR GET PUT" getArticleR :: HasReps t ⇒ ArticleId → Handler t putArticleR :: HasReps t ⇒ ArticleId → Handler t Request data, Parameters, Cookies, Languages and other Header info See ref. Authentication and authorization See ref.http://www.yesodweb.com/book/authentication-and-authorization book - Authentication and Authorization Yesodweb.com 2012-10-23 Authentication plugins: OpenId, BrowserId, Email, GoogleEmail, HashDB, RpxNow.http://hackage.haskell.org/package/yesod-auth The yesod-auth package Hackage.haskell.org 2012-10-26 There is an important setting for automatic redirection after authentication.http://www.yesodweb.com/book/sessions book - Sessions - See section "Ultimate Destination" Yesodweb.com 2012-11-17 Sessions See ref.http://www.yesodweb.com/book/sessions Sessions Yesodweb.com 2012-10-23 Session back-ends: ClientSessionhttp://hackage.haskell.org/packages/archive/clientsession/latest/doc/html/Web-ClientSession.html Web.ClientSession Hackage.haskell.org 2012-10-25 (it stores the session in a cookie), ServerSessionhttp://hackage.haskell.org/package/serversession ServerSession: secure modular server-side sessions Hackage.haskell.org 2018-10-29http://hackage.haskell.org/package/serversession-frontend-yesod Web.ServerSession.Frontend.Yesod Hackage.haskell.org 2018-10-29 (it stores most of the session data at the server) >> To avoid undue bandwidth overhead, production sites can serve their static content from a separate domain name to avoid the overhead of transmitting the session cookie for each request Session messages A success, failure or indicative message can be stored (setMessage) in the Session and will be shown, if it exists, by the default_layout routine through the default_layout.hamlet template, being cleared on consultation.https://www.yesodweb.com/book/sessions#sessions_messages Session Messages Yesodweb.com 2018-10-23 Subsites Common URL prefix subsites for workflows, file serving or site partitioning. See ref.http://www.yesodweb.com/book/creating-a-subsite Creating a Subsite Yesodweb.com 2012-10-25http://monoid.se/haskell/yesod-and-subsites/ Yesod and subsites: a no-brainer Monoid.se 2012-08-22 2012-10-28[] Built-in subsites: Static,http://www.yesodweb.com/blog/2010/12/magic-of-yesod-part2 The Magic of Yesod, part 2 - See section "Static Subsite" Yesodweb.com 2010-12-25 2012-10-25http://hackage.haskell.org/packages/archive/yesod-static/latest/doc/html/Yesod-Static.html The package yesod-static - Static Subsite Hackage.haskell.org 2012-10-25 Authhttp://hackage.haskell.org/packages/archive/yesod-auth/latest/doc/html/Yesod-Auth.html The package yesod-auth - Auth Subsite Hackage.haskell.org 2012-10-25 Form processing and layout generation See ref.http://www.yesodweb.com/book/forms book - Forms Yesodweb.com 2012-10-23 The Form type here is an object that is used in the controller to parse and process the form fields user input and produce a (FormResult, Widget) pair were the widget holds the layout of the next rendering of the form with error messages and marks. It can also be used to generate a new form with blanks or default values. The form type takes the shape of a function of an html snippet to be embedded in the view, that will hold security purpose hidden fields. A form object is generated from an Applicative/Monadic composition of fields for a combined/sequential parsing of field inputs. There are three types of forms: Applicative (with tabular layout), Monadic (with free layout style), both in the Yesod.Form.Functions module, Input (for parsing only, no view generated) in the Yesod.Form.Input module. The field generators, whose names are composed by the form type initial (a|m|i) followed by (req|opt){- required or optional -}, have a fieldParse component and a fieldView one.http://hackage.haskell.org/packages/archive/yesod-form/latest/doc/html/Yesod-Form-Fields.html Yesod.Form.Fields Hackage.haskell.org 2012-10-23 the function runForm{Post|Get} runs the field parsers against the form field inputs and generates a (FormResult, Widget) pair from the views offering a new form widget with the received form field values as defaults. The function suffix is the http method used in the form submission. while generateForm{Post|Get} ignores inputs from the client and generates a blank or defaults form widget.http://hackage.haskell.org/packages/archive/yesod-form/latest/doc/html/Yesod-Form-Functions.html#v:runFormPost Yesod.Form.Functions runFormPost Hackage.haskell.org 2012-10-25 The actual function parameters and types have changed through Yesod versions. Check the Yesod book and libraries signatures. The magic is in the FormResult data type Applicative instance, where (<*>) collects the error messages for the case of FormFailure [textErrMsg] result valueshttp://hackage.haskell.org/packages/archive/yesod-form/latest/doc/html/Yesod-Form-Types.html#t:FormResult Yesod.Form.Types Hackage.haskell.org 2012-10-23 Monadic forms permit free form layout and better treatment of hiddenField members. A sample of an Applicativehttp://www.haskell.org/haskellwiki/Applicative_functor HaskellWiki - Applicative functor haskell.org 2012-10-24 form: -- a record for our form fields data Person = Person {personName :: Text, personAge :: Int, personLikings :: Maybe Text} -- the Form type has an extra parameter for an html snippet to be embedded, containing a CSRF token hidden field for security type Form sub master x = Html → MForm sub master (FormResult x, Widget) {- -- for messages in validation functions: @param master: yesod instance to use in renderMessage (return from handler's getYesod) @param languages: page languages to use in renderMessage -- optional defaults record: @param mbPersonDefaults: Just defaults_record, or Nothing for blank form -} personForm :: MyFoundationType → [Text] → Maybe Person → Form sub master Person {- ''aopt'' (optional field AForm component) for "Maybe" fields, ''areq'' (required fld AForm comp.) will insert the "required" attribute -} personForm master languages mbPersonDefaults = renderTable $ Person <$> areq textField fldSettingsName mbNameDefault <*> areq customPersonAgeField fldSettingsAge mbAgeDefault <*> aopt textareaField fldSettingsLikings mbLikingsDefault where mbNameDefault = fmap personName mbPersonDefaults mbAgeDefault = fmap personAge mbPersonDefaults mbLikingsDefault = fmap personLikings mbPersonDefaults -- "fieldSettingsLabel" returns an initial fieldSettings record -- recently the "FieldSettings" record can be defined from a String label since it implements IsString fldSettingsName = (fieldSettingsLabel MsgName) {fsAttrs = [("maxlength","20")]} fldSettingsAge = fieldSettingsLabel MsgAge fldSettingsLikings = (fieldSettingsLabel MsgLikings) {fsAttrs = [("cols","40"),("rows","10")]} customPersonAgeField = check validateAge intField validateAge y | y < 18 = Left $ renderMessage master languages MsgUnderAge | otherwise = Right y References 2 100% __NOTOC__