2016-10-02 26 views
2

如何與僕人一起處理常規表單POST?特別是,鑑於HTML表單一樣與僕人一起處理常規表單帖子(application/x-www-form-urlencoded)

<form action="/check" method="post"> 
    Solution: 
    <input name="code" type="text"> 
    <input type="submit"> 
</form> 

data CheckResult = Correct | Wrong 

instance ToHtml CheckResult 
    ... 

checkCode :: Text -> Handler CheckResult 
checkCode code = if code == "secret" then Correct else Wrong 

我怎麼串的東西放在一起?

回答

1

僕人通過數據類型FormUrlEncodedFromFormUrlEncoded(在僕人0.9中更名爲FromForm)支持此功能。

首先我們爲表單數據定義一個數據類型,然後重寫我們的處理程序來接受它。

data CheckRequest = CheckRequest { code :: Text } 

checkCode :: CheckRequest -> Handler CheckResult 
checkCode (CheckRequest code) = if code == "secret" then Correct else Wrong 

然後我們指定一個類型爲application/x-www-form-urlencoded的POST主體。

type API = "check" 
     :> ReqBody '[FormUrlEncoded] CheckRequest 
     :> Post '[HTML] CheckResult 

現在所有的需要的是使CheckRequestFromFormUrlEncoded一個實例。

instance FromFormUrlEncoded CheckRequest where 
    --fromFormUrlEncoded :: [(Text, Text)] -> Either String CheckRequest 
    fromFormUrlEncoded [("code", c)] = Right (CheckRequest c) 
    fromFormUrlEncoded _    = Left "expected a single field `code`" 
0

我只是想補充一個答案了最新版本的僕人,因爲我不得不穀歌以組裝的形式處理一個完整的,工作版本的各種事情。

上面的答案適用於早期版本的僕人,但當升級到僕人0.9時,我被卡住了。

下面是我做到的。

首先,他們從自定義表單實現切換到一個在http-api-data,所以你需要在你的陰謀文件:

一些-project.cabal

build-depends:  base >= 4.7 && < 5 
        , aeson 
        , blaze-html 
        , http-api-data 

接下來,您可以聲明一個表單,如上所述,但您可以使用GHC.Generics自動派生FromForm實例:

{-# LANGUAGE DeriveGeneric  #-} 

module Html.Contact where 

import   GHC.Generics 
import   Servant 
import   Web.FormUrlEncoded   (FromForm) 

data ContactForm = ContactForm 
{ cname :: !T.Text 
, cemail :: !T.Text 
, cmessage :: !T.Text 
} deriving (Eq, Show, Generic) 

instance FromForm ContactForm 

之後,你就可以在你的終端使用常規的FormUrlEncoded的ContentType從僕人:

type ContactApi = "contact" :> ReqBody '[FormUrlEncoded] ContactForm 
            :> Post '[HTML] Html 

差點忘了:如何使事情

您還需要一個網頁,很可能,在那裏你正在顯示你的表單?那麼,「名稱」屬性必須匹配您的表單中的字段(以下是我如何使用Blaze):

contactForm :: H.Html 
contactForm = H.section ! A.id "contact" ! A.class_ "container contact-us u-full-width u-max-full-width" $ 
    H.div ! A.class_ "row" $ do 
    H.div ! A.class_ "eight columns contact-us-form" $ 
     H.form ! A.method "post" ! A.action "/contact" $ do 
     H.div ! A.class_ "row" $ do 
      H.div ! A.class_ "six columns" $ 
      H.input ! A.class_ "u-full-width" ! A.type_ "text" ! A.name "cname" ! A.placeholder "Name" ! A.id "nameInput" 
      H.div ! A.class_ "six columns" $ 
      H.input ! A.class_ "u-full-width" ! A.type_ "text" ! A.name "cemail" ! A.placeholder "Email" ! A.id "emailInput" 
     H.textarea ! A.class_ "u-full-width" ! A.name "cmessage" ! A.placeholder "Message" ! A.id "messageInput" $ "" 
     H.input ! A.class_ "button u-pull-right" ! A.type_ "submit" ! A.value "Send"