Headline

Technology:CGI style Web programming in Language:Haskell

Motivation

The implementation demonstrates Technology:CGI style web programming in Language:Haskell. We make use of a CGI library for Haskell. A Language:XHTML combinator library is used for the composition of dynamic web pages. The system:Company is implemented as a web application using a client-server architecture. The company is stored in a client-side cookie. (The server initializes the cookie with a sample company.) The server processes HTTP requests from and returns HTTP responses to a web client using the CGI technology. Request parameters are extracted from the request's URL in the sense of Technology:HTTP's GET parameters. The user can either request to view a company, department, or employee; the user can also cut salaries or save edits in the selected scope. The part to be viewed, cut or saved is specified by making use of a Zipper-inspired focus concept that is also leveraged by Contribution:wxHaskell. Such a focus parameter is included into the URL.

Illustration

The server is set up as follows:

main = runCGI $ handleErrors cgiMain

We use a default error handler provided by the CGI library Network.CGI.

cgiMain
is the main request handler, which is shown in the next section. In the following we will demonstrate how a specific request is processed by the server.

Cutting an employee's salary

Scenario: After receiving an employee view the user clicks the cut button in the browser. The browser sends a request to the server using this URL:

http://localhost/cgi-bin/HaskellCgi/company.cgi?focus=EmployeeFocus%20[1,0,0]%200& action=Cut

Because of the fact that the CGI library does not support any extraction of information out of the URL path (as opposed to the happstack implementation), parameters are encoded as URL parameters:

  • The action (here
    Cut
)
  • The focus (here
    EmployeeFocus [1,0,0]
)

Main request handler

The main request handler is defined as follows:

cgiMain :: CGI CGIResult
cgiMain =  do
    f <- getInput "focus"
    let focusP = maybe CompanyFocus read f
    a <- getInput "action"
    let actionP = maybe View read a
    chtml <- (doAction actionP) focusP
    let title = "101companies WebApp" 
    output $ renderHtml $ page title $ chtml
      where
        doAction ap = case ap of
          View  -> doView
          Cut   -> doCut
          Save  -> doSave 

We are working inside the

CGI
monad, which is provided by the CGI library. In lines 3 and 5
getInput :: MonadCGI m => String -> m (Maybe String)
tries to get the focus and action input parameters as
String
values, which we process in lines 4 and 6. If a parameter is set, that is,
getInput
returns
Just a
, we
read
the String to values of
Focus
and
Action
. If a parameters is not set, we use a default focus respectively a default action.

We call

doAction
, which is defined in lines 11-14. Based on the
Action
value
doAction
returns one of the action functions
doView
,
doCut
or
doSave
. In this scenario the
case
expression matches on
Cut
and
doAction
returns
doCut
.
cgiMain
applies the focus to the action function in line 7. The action function returns an
Html
value, which is used in line 9 as the content of a new page, rendered to an HTML document and returned as the
CGIResult
.

Cutting the cookie

The function

doCut
performs the actual cut action on the company cookie:

doCut :: Focus -> CGI Html
doCut f = do
    c <- tryReadCCookie
    let cutC = readCutWrite f c   
    writeCCookie cutC
    return $ html f cutC

The company cookie is read using

tryReadCCookie
:

tryReadCCookie = liftM (fromMaybe company) $ 
                 readCookie "companyCookie"

This function tries to read the company cookie. If the client does not have this cookie stored, the default company is returned. In line 4

doCut
calls
readCutWrite
, which reads a company, department or employee based on the focus, cuts it and replaces it within the company (see this!!Cut.hs for details). In line 5 the manipulated company is written back into the cookie using
writeCCookie
:

writeCCookie s = setCookie $ 
                 newCookie "companyCookie" $ 
                 show s    

Returning HTML

After the company data is saved in the cookie

doCut
calls
html
passing the focus and the new company:

html :: Focus -> Company -> Html
html f = case f of 
  CompanyFocus        -> companyHtml f
  (DeptFocus  )       -> deptHtml f
  (EmployeeFocus    ) -> employeeHtml f
  (ManagerFocus  )    -> employeeHtml f   

Based on the focus

html
calls one of the functions for composing HTML. In this scenario
case
matches on
(EmployeeFocus    )
and
employeeHtml
is called. This function composes HTML for the employee in question using various HTML combinators (see this!!CompanyHtml.hs for details).

Architecture

In this!!Main.hs the server is set up using request handlers provided by this!!Response.hs. The save actions are performed by functionality hosted by this!!Save.hs. An algebraic datatype for actions is definied in this!!Types.hs. HTML pages are composed in this!!CompanyHtml.hs. The algebraic datatype for companies can be found in this!!Company.hs. this!!Focus.hs provides a focus datatype and functions on top of it. A sample company can be found in this!!SampleCompany.hs. this!!Cut.hs and this!!Total.hs provide cut and total functionality.

Usage

  • First you need a webserver. In the following we explain the steps for XAMPP<cite>xampp</cite>.
  • Compile this!!Main.hs to a CGI file using GHC:
    Invalid Language supplied
  • Place company.cgi in the folder cgi-bin of your XAMPP installation.
  • Place this!!style.css in the folder htdocs of your XAMPP installation.
  • Open http://localhost/cgi-bin/haskellCGI/company.cgi in a web browser to see the application's root view.
Compiling the project is scripted by the run target in this!!Makefile.hs.


There are no revisions for this page.

User contributions

    This user never has never made submissions.

    User edits

    Syntax for editing wiki

    For you are available next options:

    will make text bold.

    will make text italic.

    will make text underlined.

    will make text striked.

    will allow you to paste code headline into the page.

    will allow you to link into the page.

    will allow you to paste code with syntax highlight into the page. You will need to define used programming language.

    will allow you to paste image into the page.

    is list with bullets.

    is list with numbers.

    will allow your to insert slideshare presentation into the page. You need to copy link to presentation and insert it as parameter in this tag.

    will allow your to insert youtube video into the page. You need to copy link to youtube page with video and insert it as parameter in this tag.

    will allow your to insert code snippets from @worker.

    Syntax for editing wiki

    For you are available next options:

    will make text bold.

    will make text italic.

    will make text underlined.

    will make text striked.

    will allow you to paste code headline into the page.

    will allow you to link into the page.

    will allow you to paste code with syntax highlight into the page. You will need to define used programming language.

    will allow you to paste image into the page.

    is list with bullets.

    is list with numbers.

    will allow your to insert slideshare presentation into the page. You need to copy link to presentation and insert it as parameter in this tag.

    will allow your to insert youtube video into the page. You need to copy link to youtube page with video and insert it as parameter in this tag.

    will allow your to insert code snippets from @worker.