OS Web-Apps

in Yesod

WAI/Warp - Router/Handler

Stefan von der Krone
11 MIM

Web Application Interface (WAI)

  • Low-Level-Interface zw. Web-Server und Web-App
  • Allgemeine Web-Schnittstelle für Haskell
  • vgl.
    • CGI
    • Web Server Gateway Interface (Python)
    • Rack (Ruby)
  • implementiert von
    • Yesod
    • Happstack (in Arbeit)
    • Hoogle

WAI

  • Funktion: Request -> Response
  • Lazy IO:
    • geringer Speicherverbrauch
    • ByteString

WAI

Simples Beispiel:
{-# LANGUAGE OverloadedStrings #-}
import Network.Wai
import Network.HTTP.Types (status200)
import Network.Wai.Handler.Warp (run)

application _ = return $
  responseLBS status200 [("Content-Type", "text/plain")] "Hello World"

main = run 3000 application

WAI

Middleware
{-# LANGUAGE OverloadedStrings #-}
import Network.Wai
import Network.Wai.Handler.Warp (run)
import Network.Wai.Middleware.Gzip (gzip, def)
import Network.HTTP.Types (status200)

application _ = return $
  responseLBS status200 [("Content-Type", "text/plain")] "Hello World"

main = run 3000 $ gzip def application

Warp

  • Web-Server für Yesod
  • implementiert WAI
  • extrem schnell

Warp-Benchmark

Mit Vorsicht zu betrachten!!!

Warp-Benchmark

Mit Vorsicht zu betrachten!!!

Warp

Beispiel-App:
app req = return $
  case pathInfo req of
    ["yay"] -> yay      -- url-bestandteile ohne query-string
    x       -> index x  -- evtl. 404
yay = ResponseBuilder status200 ...

index x = ResponseBuilder status200 ...

Deploy Yesod

Beispiel für nginx
...server {
    listen 80;
    server_name www.myserver.com;
    location / {
        proxy_pass http://127.0.0.1:3000;
    }
}...

Routes

  • ermöglicht durch eigene DSL
    • TemplateHaskell
  • Prinzip:
/                 HomeR      METHOD
/route            RouteR     METHOD METHOD
/route/#routeVar  RouteVarR  METHOD
/route/*routeVars RouteVarsR METHOD

/static           StaticR    Static getStatic

Routes

  • jede Route wird durch eine Resource repräsentiert
  • jede Route benötigt einen Handler
    • muss explizit geschrieben werden
    • es gibt keinen default-Handler

Handler

  • bestimmen das Verhalten für die Routen
  • werden per TemplateHaskell automatisch erzeugt
/route RouteR METHOD ...
-- wird zu
methodRoute :: Handler Html

Handler

  • HTTP sieht GET, POST, DELETE uvm. vor
  • Yesod prüft den Methoden-Namen nicht
    • eigene Methoden möglich, z.B: 
      • DOWNLOAD
      • STREAM
  • Yesod ruft automatisch passende Handler auf

Handler-Beispiele

GET:
-- route
/route RouteR GET
-- handler
getRoute :: Handler -> Html
POST:
-- route
/route RouteR POST
-- handler
postRoute :: Handler -> Text
Keine Methode:
-- route
/route RouteR
-- handler
handleRoute :: Handler -> Html

Path-Piece(s)

  • einzelne Bestandteile der URL
  • relevant für dynamische URLs
    • dynamic single
    • dynamic multi

Path-Piece(s)

Single Path-Piece:
-- route/route/#URLType RouteR METHOD
-- PathPiece methodsinstance PathPiece URLType where toPathPiece (URLType t) = toPathPiece t fromPathPiece p = do t <- fromPathPiece p return $ URLType t fromPathPiece _ = Nothing -- nicht immer erforderlich, evtl. 404?

Path-Piece(s)

Single Path-Piece:
instance PathPiece Bool where  toPathPiece b = toPathPiece (if b then 1 else 0 :: Int)  fromPathPiece p = do    x <- fromPathPiece p    case x :: Int of      0 -> return False      1 -> return True      _ -> Nothing

Path-Piece(s)

Multiple Path-Pieces:
-- route/route/*URLType RouteR METHOD
-- PathMultiPiece methodsinstance PathMultiPiece URLType where toPathMultiPiece (URLType t1 t2) = [toPathPiece t1, toPathPiece t2] fromPathMultiPiece [p1,p2] = do t1 <- fromPathPiece p1 t2 <- fromPathPiece p2 return $ URLType t1 t2 fromPathMultiPiece _ = Nothing -- evtl. 404?

Path-Piece(s)

Multiple Path-Pieces:
  • evtl. müssen noch zusätzliche Single-PathPiece-Methoden für eigene Datentypen implementiert werden

Binary-Yesod-App

  • Beispiel-App
  • Umwandeln von binären Zahlen in natürliche
  • und andersrum

Binary-Yesod-App

Daten-Typen:
data Natural = Natural Integer deriving (Eq, Show, Read)
data Binary = Binary String deriving (Eq, Show, Read)

Binary-Yedod-App

Der Binary-Datentyp:
toBinary :: Natural -> Binary
toBinary n = Binary $ getBinary $ fromNatural n where
  getBinary i = showIntAtBase 2 intToDigit i ""

fromBinary :: Binary -> String
fromBinary (Binary b) = b

Binary-Yesod-App

Der Natural-Datentyp:
toNatural :: Binary -> Natural
toNatural b = Natural $ bin2dec $ fromBinary b where
  bin2dec = foldr (\c s -> s * 2 + c) 0 . reverse . map c2i where
  c2i '0' = 0
  c2i '1' = 1
  c2i _ = error "no binary"

fromNatural :: Natural -> Integer
fromNatural (Natural n) = n

Binary-Yesod-App

And Action...

Quellen

  • www.yesodweb.com
  • hackage
  • haskell-wiki
  • detailliert im Git-Repo

OS Yesod - WAI/Warp & Router/Handler

By Stefan Von Der Krone

OS Yesod - WAI/Warp & Router/Handler

  • 623