如何使用Servant处理常规表单POST?特别是,给出像
这样的HTML表单<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type="button" id="myBtn">Load Data</button>
<div class="dictionary-stack"></div>
和
<form action="/check" method="post">
Solution:
<input name="code" type="text">
<input type="submit">
</form>
如何将事物串在一起?
答案 0 :(得分:4)
我只是想为最新版本的Servant添加答案,因为我必须谷歌各种各样的东西,以便组装一个完整的,工作版本的表单处理。
上述答案适用于早期版本的Servant,但在升级到Servant 0.9时,我无法使用表单。
我是这样做的。
首先,他们从自定义表单实现切换到http-api-data中的表单实现,因此您需要在您的cabal文件中:
一些-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
之后,您可以在终端中使用来自Servant的常规FormUrlEncoded
ContentType:
type ContactApi = "contact" :> ReqBody '[FormUrlEncoded] ContactForm
:> Post '[HTML] Html
几乎忘了:如何渲染
您可能还需要一个页面,显示您的表单?好吧,“name”属性必须与表单中的字段匹配(以下是我使用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"
答案 1 :(得分:3)
Servant通过数据类型FormUrlEncoded和类FromFormUrlEncoded(在Servant 0.9中重命名为data CheckResult = Correct | Wrong
instance ToHtml CheckResult
...
checkCode :: Text -> Handler CheckResult
checkCode code = if code == "secret" then Correct else Wrong
)支持此功能。
首先,我们为表单数据定义数据类型,并重写我们的处理程序以接受它。
FromForm
然后我们指定一个data CheckRequest = CheckRequest { code :: Text }
checkCode :: CheckRequest -> Handler CheckResult
checkCode (CheckRequest code) = if code == "secret" then Correct else Wrong
类型的POST主体。
application/x-www-form-urlencoded
现在所需要的只是让type API = "check"
:> ReqBody '[FormUrlEncoded] CheckRequest
:> Post '[HTML] CheckResult
成为CheckRequest
的实例。
FromFormUrlEncoded