在Haskell和Yesod中返回错误状态

Ral*_*lph 9 haskell http-status-codes yesod

我是Haskell的新手.

我正在尝试使用Yesod Framework编写一个小型Webdav服务器,并在Apache Tomcat 7源代码之后进行建模.我遇到了一个从我的一个函数返回错误的问题.WebdavServlet

我的webdav服务应该返回XML或JSON,具体取决于Accept调用者发送的标头的值.我定义了一个名为的数据类型RepXmlJson:

import Yesod

data RepXmlJson = RepXmlJson RepXml RepJson

instance HasReps RepXmlJson where
  chooseRep (RepXmlJson (RepXml xml) (RepJson json)) = chooseRep
    [ (typeXml, xml)
    , (typeJson, json)
    ]
Run Code Online (Sandbox Code Playgroud)

我使用此数据类型作为我的服务的返回值,特别是lockWebdavR函数.如果资源当前被锁定,我试图返回状态423(已锁定).我的代码看起来像这样:

import qualified Data.ByteString as B
import qualified Data.Map        as M
import qualified Data.Text       as T
import qualified Network.Wai     as W

mkYesodSub "Webdav" [] [parseRoutes|
  / WebdavR COPY DELETE LOCK MKCOL MOVE OPTIONS PROPFIND PROPPATCH PUT UNLOCK
|]

type WebdavHandler yesod = GHandler Webdav yesod

webdavLocked423 :: Status
webdavLocked423 = Status 423 "Locked"

isLockedRequest :: Yesod master => Request -> WebdavHandler master Bool
-- isLockedRequest definition omitted for brevity

lockWebdavR :: Yesod master => WebdavHandler master RepXmlJson
lockWebdavR = do
  request <- getRequest
  locked <- isLockedRequest request
  if locked
    then return $
      W.responseLBS webdavLocked423 [("Content-Type", "text/plain")] ""
    else return undefined
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

Webdav.hs:94:10:
    Couldn't match expected type `RepXmlJson'
                with actual type `W.Response'
    Expected type: GHandler Webdav master RepXmlJson
      Actual type: GHandler Webdav master W.Response
    In the expression:
      return
      $ W.responseLBS webdavLocked423 [("Content-Type", "text/plain")] ""
    In a stmt of a 'do' block:
      if locked then
          return
          $ W.responseLBS webdavLocked423 [("Content-Type", "text/plain")] ""
      else
          return undefined
Run Code Online (Sandbox Code Playgroud)

我搜索了"使用Haskell和Yesod开发Web应用程序"一书,但找不到返回正确类型错误(Rep...)的示例.

如何RepXmlJson使用正确的错误状态创建?

Mic*_*man 5

正常完成处理程序始终会生成200状态代码.要覆盖它,您必须以其他方式发送响应.在你的情况下,你可以尝试sendResponseStatus.其他可能会sendWaiResponseredirectWith,虽然我怀疑后者将是有益的.