泚æãåŒãç»åã§ããclckwrksã¯ãHappstackã«å¯æ¥ã«ãªã³ã¯ãããWebãã¬ãŒã ã¯ãŒã¯ã§ããHappstackã¯ãéå»7幎éã«ããã£ãŠæ¥ã
ã®Webéçºã®ããŒãºãæºããããã«é²åããŠããè±å¯ãªAPIãåããã
åªãã
æ©èœãåãã Webãã¬ãŒã ã¯ãŒã¯ã§ãã æ®å¿µãªããããªããã§æè»ãªAPIã¯ãåçŽãªãã®ãå¿
èŠãªãšãã«åœ¹ã«ç«ãããæ··ä¹±ãæãå¯èœæ§ããããŸãã ããããå€ãã®äººã¯ãHappstackã®ç¿Œã®äžã«éåžžã«ãšã¬ã¬ã³ãã§äœ¿ããããHappstack Lite Webãã¬ãŒã ã¯ãŒã¯ãããããšã«æ°ä»ããŠããŸããã
ãŸããã
Happstack Liteã¯æ§é ãã·ã³ãã«ã§ãHappstackã®äœ¿ããããããŒãžã§ã³ã§ãã ãããäœæããããã«ãéçºè
ã¯ïŒ
- åäžã®
Happstack.Lite
ã¢ãžã¥ãŒã«ã§Webã¢ããªã±ãŒã·ã§ã³ãéçºããããã«å¿
èŠãªãã¹ãŠã®åºæ¬çãªã¿ã€ããšæ©èœãã³ã³ãã€ã«ãããããå¿
èŠãªã¢ãžã¥ãŒã«ãHappstack.Lite
å¿
èŠã¯ãããŸããã - ãããã¯é¢æ°ã«ãã£ãšã·ã³ãã«ãªã·ã°ããã£ãäžããã¢ãã倿åãæé€ããã»ãšãã©ã®åã¯ã©ã¹ãåãé€ããŸããã
- ãã®ãã¥ãŒããªã¢ã«ãäœæããŸãããWebã¢ããªã±ãŒã·ã§ã³ã®äœæãéå§ããããã«ç¥ã£ãŠããå¿
èŠããããã¹ãŠã®åºæ¬äºé
ã2,000èªæªæºã§èª¬æããŠããŸãã
ããããæãéèŠãªããš-Happstack Liteã¯Happstackãšã»ãŒå®å
šã«äºææ§ããããŸãïŒ Happstack Liteã§ã¢ããªã±ãŒã·ã§ã³ãéçºããŠããŠãHappstackã®é«åºŠãªæ©èœãå¿
èŠãªå Žåã¯ã察å¿ããã¢ãžã¥ãŒã«ãã€ã³ããŒãããŠäœ¿çšããã ãã§ãã
Happstack Liteããéåžžã®ãããžã§ã¯ãã«ç§»è¡ããã«ã¯ã4ã€ã®å°ããªå€æŽãå ããã ãã§ãã
import Happstack.Lite
眮ãæãimport Happstack.Server
simpleHTTP nullConf
serve Nothing
simpleHTTP nullConf
眮ãæãserve Nothing
import Control.Monad (msum)
远å - æç€ºçãª
decodeBody
åŒã³åºãã远å ïŒ è©³çŽ° ïŒ
Happstack Liteã¯ãéåžžã®Happtsackãšæ¯èŒããŠè»œéã§ãããä»ã®Haskell Webãã¬ãŒã ã¯ãŒã¯ãšãšãã«å®å
šã«æ©èœãããã¬ãŒã ã¯ãŒã¯ã§ãã
åçŽåããããã«ãéçºè
ã¯Happstackã§åäœããããã€ãã®é«åºŠãªã©ã€ãã©ãªã®äœ¿çšãæŸæ£ããŸããã ã¿ã€ãã»ãŒãURLãã¿ã€ãã»ãŒããã©ãŒã ãHTMLãªãã©ã«æ§æãªã©ãåãããã¬ãŒã ã¯ãŒã¯ã«èå³ãããå Žåã¯ãHappstack Foundationãæ€èšããããšããå§ãããŸãã åŠç¿æ²ç·ã¯é«ããªããŸããã远å ãããä¿¡é Œæ§ã«ã¯äŸ¡å€ããããŸãã ãããã®ã©ã€ãã©ãªã¯Happstackã³ã¢ã®äžã«æ§ç¯ãããŠããããããã®ãã¥ãŒããªã¢ã«ã§åŠç¿ããè³æã¯ã¢ããªã±ãŒã·ã§ã³ã§ã圹ç«ã¡ãŸãã
詳现ã«ã€ããŠã¯ã
Happstackã¯ã©ãã·ã¥ã³ãŒã¹ããèªã¿ãã ããïŒ
ãã®èšäºã«é¢å¿ã衚æãããŠããå Žåã¯ç¿»èš³ããŸã-çŽPer ïŒ
ãµãŒããŒèµ·å
ãŸããããã€ãã®èšèªæ¡åŒµæ©èœãå¿
èŠã§ãã
{-# LANGUAGE OverloadedStrings, ScopedTypeVariables #-}
次ã«ãããã€ãã®ã©ã€ãã©ãªãæ¥ç¶ããŸãã
module Main where import Control.Applicative ((<$>), optional) import Data.Maybe (fromMaybe) import Data.Text (Text) import Data.Text.Lazy (unpack) import Happstack.Lite import Text.Blaze.Html5 (Html, (!), a, form, input, p, toHtml, label) import Text.Blaze.Html5.Attributes (action, enctype, href, name, size, type_, value) import qualified Text.Blaze.Html5 as H import qualified Text.Blaze.Html5.Attributes as A
ã¢ããªã±ãŒã·ã§ã³ãèµ·åããã«ã¯ã
serve
颿°ãåŒã³åºããŸãã æåã®åŒæ°ã¯æ§æã§ããããªãã·ã§ã³ã§ãã 2çªç®ã®åŒæ°ã¯ãWebã¢ããªã±ãŒã·ã§ã³èªäœã§ãã
main :: IO () main = serve Nothing myApp
Webã¢ããªã±ãŒã·ã§ã³ã®ã¿ã€ãã¯
ServerPart Response
ã§ãã
ServerPart
ã¯
IO
ã¢ããã«çžåœ
ServerPart
WebãšèŠãªãããšãã§ããŸãã
ïŒ
ããã©ã«ãã§ã¯ãããŒã8000ââã䜿çšãããŸããã€ãŸãã httpïŒ// localhostïŒ8000 / -ã§ã¢ããªã±ãŒã·ã§ã³ã確èªã§ããŸããéçã¢ãã¬ã¹
Webã¢ããªã±ãŒã·ã§ã³ã¯æ¬¡ã®ãšããã§ãã
myApp :: ServerPart Response myApp = msum [ dir "echo" $ echo , dir "query" $ queryParams , dir "form" $ formPage , dir "fortune" $ fortune , dir "files" $ fileServing , dir "upload" $ upload , homePage ]
æãäžè¬çãªåœ¢åŒã§ã¯ãã¢ããªã±ãŒã·ã§ã³ã¯éçã¢ãã¬ã¹ã«ãããã³ã°ãããã»ãã®æ°åã®ãã³ãã©ãŒã§ãã
dir
ãéçãã¹ã³ã³ããŒãã³ããæ£åžžã«ããããããå Žåã«ã®ã¿ãã³ãã©ãŒãå®è¡ãããããã«äœ¿çšãããŸãã ããšãã°ã
dir "echo"
ã¯ã¢ãã¬ã¹ã§æ£åžžã«æ©èœããŸã
localhost:8000/echo
localhost:8000/echo
ã ãã³ãã©ãã¢ãã¬ã¹
"/foo/bar"
ã«å²ãåœãŠãã«ã¯ã
dir "foo" $ dir "bar" $ handler
æžãã ãã§ãã
åãã³ãã©ãŒãæåããçµæãè¿ããŸã§ãåãã³ãã©ãŒãé çªã«é©çšããããšããŸãã ãã®å Žåã
Response
ã
msum
ã䜿çšããŠãã³ãã©ãŒã®ãªã¹ããåäžã®ãªã¹ãã«å€æããŸãã
æåŸã®ãã³ãã©ãŒ
homePage
ã¯äœã«ãå¶éãããŸããïŒ
dirã¯é©çšãããŸãã-ãããPerã ïŒããããã£ãŠãä»ã®ãã³ãã©ãŒãã©ããæ£åžžã«åäœããªãå Žåã¯åžžã«åŒã³åºãããŸãã
HTMLãã³ãã¬ãŒã
Webã¢ããªã±ãŒã·ã§ã³ãäœæããŠãããããHTMLããŒãžãäœæããå¿
èŠããããŸãã ããã«ã¯Blazeã䜿çšã§ããŸããBlazeã«ã¯
ãã¥ãŒããªã¢ã«ããããŸãã
HTMLãã³ãã¬ãŒãã®ããŒãã¯ãã³ãã¥ããã£ã§åºãè°è«ãããŠããŸãã 誰ããæºè¶³ã§ãããã³ãã¬ãŒãã·ã¹ãã ã¯ãªããããHappstackã¯ããŸããŸãªã·ã¹ãã ããµããŒãããŠããŸãã ãã®ãã¥ãŒããªã¢ã«ã§ã¯ãçŽç²ã«æ©èœçãªã³ã³ãããŒã¿ãŒã«åºã¥ããŠãµããŒããããŠãããããBlazeã䜿çšããŸãã ã³ã³ãã€ã«æã®ãã¿ãŒã³ã奜ãã§ãHTMLæ§æãå¿
èŠãªå Žåã¯ãHSPãæ€èšã§ããŸãã ã³ãŒãå
ã®ãã³ãã¬ãŒãã«åŠå®çã§ãå€éšXMLãã¡ã€ã«ã奜ãå Žåã¯ãHeistãæ€èšããŠãã ããã
CSSãå€éšJSãã¡ã€ã«ãã¡ãã¥ãŒãªã©ã®ã€ã³ããŒããªã©ãWebã¢ããªã±ãŒã·ã§ã³ã®ãã¹ãŠã®ããŒãžã«å
±éã®èŠçŽ ãçµåãããã³ãã¬ãŒã颿°ããããšäŸ¿å©ã§ãããã®ãã¥ãŒããªã¢ã«ã§ã¯ãéåžžã«åçŽãªãã³ãã¬ãŒãã䜿çšããŸãã
template :: Text -> Html -> Response template title body = toResponse $ H.html $ do H.head $ do H.title (toHtml title) H.body $ do body p $ a ! href "/" $ " "
次ã«ãã¡ã€ã³ããŒãžã¯æ¬¡ã®ããã«ãªããŸãã
homePage :: ServerPart Response homePage = ok $ template " " $ do H.h1 "!" Hp " Happstack Lite !" Hp " :" Hp $ a ! href "/echo/secret%20message" $ "" Hp $ a ! href "/query?foo=bar" $ " " Hp $ a ! href "/form" $ " " Hp $ a ! href "/fortune" $ "- ()" Hp $ a ! href "/files" $ " " Hp $ a ! href "/upload" $ " "
ok
颿°ã¯ãããŒãžã®HTTPã³ãŒãã200 OKããèšå®ããŸãã ä»ã®è£å©é¢æ°ããããŸããããšãã°ã
seeOther
ã¯ã³ãŒããã404 Not Foundãã«
seeOther
ããŸãããã®ä»ã¯ã303 See Otherãã«
seeOther
ããŸãã HTTPã³ãŒããæ°å€ã§
setResponseCode
ã
setResponseCode
䜿çšãããŸãã
äœæã®åçãªéšå
dir
颿°ã¯ãã¢ãã¬ã¹ã®éçéšåã®ã¿ã«äžèŽããŸãã
path
颿°ã䜿çšããŠãã¢ãã¬ã¹ã®åçéšåããå€ãæœåºãããªãã·ã§ã³ã§
Integer
ãªã©ã®ã¿ã€ãã«å€æã§ããŸãã ãã®äŸã§ã¯ããã¹ã®åçãªéšåã衚瀺ããã ãã§ãã
httpã«ã¢ã¯ã»ã¹ããŠç¢ºèªããã«ã¯
ïŒ// localhostïŒ8000 / echo / fantastic echo :: ServerPart Response echo = path $ \(msg :: String) -> ok $ template "" $ do p $ " : " >> toHtml msg p " , - ."
ãªã¯ãšã¹ããã©ã¡ãŒã¿
æååã¯ãšãªãã©ã¡ãŒã¿ãŒã®å€ãååŸããããšãã§ããŸãã ã¯ãšãªæååã¯ãã
?foo=bar
ãã®ããã«èŠããã¢ãã¬ã¹ã®äžéš
?foo=bar
ã
httpïŒ// localhostïŒ8000 / queryã«ã¢ã¯ã»ã¹ããŠã¿ãŠãã ãã
ïŒFoo = bar queryParams :: ServerPart Response queryParams = do mFoo <- optional $ lookText "foo" ok $ template " " $ do p $ "foo = " >> toHtml (show mFoo) p $ " , foo."
ã¯ãšãªãã©ã¡ãŒã¿ãèšå®ãããŠããªãå Žåã
lookText
颿°ã¯
mzero
ãè¿ããŸãã ãã®äŸã§ã¯ã
Control.Applicative
ã¢ãžã¥ãŒã«ã®
optional
ã䜿çšããæçµçã«
Maybe
åã®å€ãååŸããŸãã
ãã©ãŒã
lookText
ã䜿çšããŠããã©ãŒã ããããŒã¿ãååŸã§ããŸãã
formPage :: ServerPart Response formPage = msum [ viewForm, processForm ] where viewForm :: ServerPart Response viewForm = do method GET ok $ template "form" $ form ! action "/form" ! enctype "multipart/form-data" ! A.method "POST" $ do label ! A.for "msg" $ " - " input ! type_ "text" ! A.id "msg" ! name "msg" input ! type_ "submit" ! value "" processForm :: ServerPart Response processForm = do method POST msg <- lookText "msg" ok $ template "form" $ do Hp " :" Hp (toHtml msg)
åã®æ®µèœãšåã
lookText
颿°ã䜿çšããŠããã©ãŒã ããããŒã¿ãååŸããŸãã ãŸãã
method
颿°ã䜿çšããŠ
GET
èŠæ±ãš
POST
èŠæ±ãåºå¥ããŠããããšã«ãæ°ã¥ããããããŸããã
ãŠãŒã¶ãŒããã©ãŒã ã衚瀺ãããšããã©ãŠã¶ã¯
GET
ã䜿çšããŠ
/form
ããŒãžãèŠæ±ããŸãã HTML
form
ã¿ã°ã§ã¯ããã¿ã³ãã¯ãªãã¯ãããšãã®ã¢ã¯ã·ã§ã³ãšããŠãåãããŒãžãéãããšã瀺ããŸãããã屿§ã䜿çšããŠ
POST
ã¡ãœãããéžæããŸããã
ã¯ãããŒïŒ ïŒHTTPã¯ãããŒïŒ
ãã®äŸã§ã¯ãã¡ãã»ãŒãžãCookieã«ä¿åããããšã«ããããã©ãŒã ã䜿çšããŠäŸãæ¡åŒµããŠããŸãã ããã¯ããŠãŒã¶ãŒãããŒãžãé¢ããããšãã§ããããšãæå³ããŸãããŠãŒã¶ãŒãæ»ããšãããŒãžã¯ä¿åãããã¡ãã»ãŒãžãèšæ¶ããŸãã
fortune :: ServerPart Response fortune = msum [ viewFortune, updateFortune ] where viewFortune :: ServerPart Response viewFortune = do method GET mMemory <- optional $ lookCookieValue "- ()" let memory = fromMaybe " -!" mMemory ok $ template "fortune" $ do Hp " - ():" Hp (toHtml memory) form ! action "/fortune" ! enctype "multipart/form-data" ! A.method "POST" $ do label ! A.for "fortune" $ " : " input ! type_ "text" ! A.id "fortune" ! name "new_fortune" input ! type_ "submit" ! value "" updateFortune :: ServerPart Response updateFortune = do method POST fortune <- lookText "new_fortune" addCookies [(Session, mkCookie "fortune" (unpack fortune))] seeOther ("/fortune" :: String) (toResponse ())
ïŒ
ç§ã¯ã©ããããããHTTP-cookieãšfortune cookieã®éã®é§æŽèœãä¿åããããšãã§ããŸããã§ãã-ãããPer ïŒ
åã®äŸãšæ¯èŒããŠãããªãæ°ãããã®ãç»å ŽããŸããã
lookCookieValue
ãŸã£ããåãããã«lookText
ããŸãããã¯ãšãªãã©ã¡ãŒã¿ããã©ãŒã ã§ã¯ãªããCookieã®å€ãæ€çŽ¢ãããšããå¯äžã®éãããããŸããaddCookies
Cookieããã©ãŠã¶ã«éä¿¡ããæ¬¡ã®ã¿ã€ãããããŸãïŒ addCookies :: [(CookieLife, Cookie)] -> ServerPart ()
CookieLife
ã¯ãCookieãååšããæ£ãããšCookieLife
ããCookieLife
決å®ããŸãã Session
ãšã¯ããã©ãŠã¶ãŠã£ã³ããŠãéãããŸã§ã®Cookieã®æå¹æéãæå³ããŸããmkCookie
ã¯ãCookieåãšãã®å€ãåãå
¥ããCookieãäœæããŸããseeOther
ïŒã€ãŸãã303ãªãã€ã¬ã¯ãïŒã¯ããã©ãŠã¶ã«/fortune
ããŒãžãžã®æ°ããGET
èŠæ±ãè¡ãããã«æç€ºããŸãã
ãã¡ã€ã«ã¢ã¯ã»ã¹
ã»ãšãã©ã®Webã¢ããªã±ãŒã·ã§ã³ã¯ãç»åãã¹ã¿ã€ã«ã·ãŒããã¹ã¯ãªãããªã©ããã£ã¹ã¯ããéçãã¡ã€ã«ãžã®ã¢ã¯ã»ã¹ãæäŸããå¿
èŠããããŸã
serveDirectory
颿°ã䜿çšããŠãããå®çŸã§ããŸãã
fileServing :: ServerPart Response fileServing = serveDirectory EnableBrowsing ["index.html"] "."
æåã®åŒæ°
serveDirectory
ã
serveDirectory
ãã£ã¬ã¯ããªå
ã®ãã¡ã€ã«ã®ãªã¹ããäœæããŠè¡šç€ºã§ããããã«ãããã©ãããæ±ºå®ããŸãã
2çªç®ã®åŒæ°ã¯ãã€ã³ããã¯ã¹ãã¡ã€ã«ã®ãªã¹ãã§ãã ãŠãŒã¶ãŒããã£ã¬ã¯ããªã®è¡šç€ºãèŠæ±ããã€ã³ããã¯ã¹ãã¡ã€ã«ãå«ãŸããŠããå Žåããã¡ã€ã«ã®ãªã¹ãã®ä»£ããã«è¡šç€ºãããŸãã
3çªç®ã®åŒæ°ã¯ãã¢ã¯ã»ã¹ãèš±å¯ããããã£ã¬ã¯ããªãžã®ãã¹ã§ãã ãã®äŸã§ã¯ãçŸåšã®ãã£ã¬ã¯ããªãžã®ã¢ã¯ã»ã¹ãæäŸããŸãã
ãµããŒããããŠãããã©ââãããã©ãŒã ïŒLinuxãOS XãWindowsïŒã§ã¯ã
serveDirectory
颿°ã¯èªåçã«
sendfile()
ã䜿çšããŠãã¡ã€ã«ã«ã¢ã¯ã»ã¹ããŸãã
sendfile()
ã¯ãäœã¬ãã«ã®ã«ãŒãã«æäœã䜿çšããŠãæå°éã®CPUè² è·ãšãããã¯ãŒã¯ãã£ãã«ã®æå€§éã®äœ¿çšã§ããã©ã€ããããããã¯ãŒã¯ã«ãã¡ã€ã«ã転éããŸãã
ãã¡ã€ã«ã®å Žæ
ãµãŒããŒãžã®ãã¡ã€ã«ã®ã¢ããããŒãã®åŠçã¯éåžžã«ç°¡åã§ãã åã®äŸã®ããã«ãã©ãŒã ãäœæããŸããã
lookText
代ããã«
lookText
䜿çšã
lookFile
ã
upload :: ServerPart Response upload = msum [ uploadForm , handleUpload ] where uploadForm :: ServerPart Response uploadForm = do method GET ok $ template " " $ do form ! enctype "multipart/form-data" ! A.method "POST" ! action "/upload" $ do input ! type_ "file" ! name "file_upload" ! size "40" input ! type_ "submit" ! value "upload" handleUpload :: ServerPart Response handleUpload = do (tmpFile, uploadName, contentType) <- lookFile "file_upload" ok $ template " " $ do p (toHtml $ " : " ++ tmpFile) p (toHtml $ " : " ++ uploadName) p (toHtml $ " : " ++ show contentType)
ãã¡ã€ã«ãã¢ããããŒãããããšãäžæçãªå Žæã«ä¿åãããŸãã ãµãŒããŒããã©ãŠã¶ã«å¿çãéä¿¡ãããšãäžæãã¡ã€ã«ã¯èªåçã«åé€ãããŸãã ããã«ãããæªäœ¿çšã®ãã¡ã€ã«ããã£ã¹ã¯é åãæ±æããªãããã«ããŸãã
ã»ãšãã©ã®å ŽåããŠãŒã¶ãŒã¯åé€ããããã ãã«ãã¡ã€ã«ãããŠã³ããŒãããå¿
èŠã¯ãããŸããã éåžžããã³ãã©ãŒã§
moveFile
ãŸãã¯
copyFile
åŒã³åºããŠããã¡ã€ã«ãæ°žç¶çãªå Žæã«ç§»åïŒãŸãã¯ã³ããŒïŒããŸãã
翻蚳è
ãã
ãã®èšäºã®èè
ã¯ãHaskellèšèªã®åºæ¬çãªç¥èãããããšãåæãšããŠããŸãã Happstackãã€ã³ã¹ããŒã«ããã«ã¯ããµã€ãã®æç€ºã«åŸã£ãŠãã ããã
ãã®ãã¬ãŒã ã¯ãŒã¯ã«èå³ãããå Žåã¯ããã«ããŒãžã§ã³ïŒããã翻蚳ãã
ã³ãŒã¹ïŒãšããã«åºã¥ãã
clckwrksãçè§£ããããšããå§ãããŸãã çŽ æŽãããéçºãïŒ