Servant QueryParams解析错误

时间:2018-07-03 03:35:30

标签: haskell servant

给出以下代码:

newtype HelloMessage = HelloMessage { msg :: String }
  deriving (Generic)

instance ToJSON HelloMessage

type API2 = "hello"
            :> QueryParam "age" Int
            :> Get '[JSON] HelloMessage

appAPI2 :: Proxy API2
appAPI2 = Proxy

myHandler :: Server API2
myHandler = helloHandler
  where
    helloHandler :: Maybe Int -> Handler HelloMessage
    helloHandler mAge =
      let
        sAge = case mAge of
                 Nothing -> "0"
                 Just ag -> show ag
      in
        return . HelloMessage $ sAge

app2 :: Application
app2 = serve appAPI2 myHandler

main :: IO ()
main = run 8080 app2

我可以访问返回/hello的{​​{1}}或返回{ "msg" : 0}的{​​{1}}。但是如果我将年龄设置为非整数可解析的,例如/hello?age=20将url设为{ "msg" : 20}并对其进行访问,它返回一条有关解析"foobar"上的错误的错误消息。

这与/hello?age=foobar的行为不同,如果我给予相同的处理,它将只返回http400。

我的代码有什么问题?

编辑:进一步研究后,解析错误确实返回http 400。现在,我要更改问题。如何返回自定义错误消息,如果  那会发生吗?

1 个答案:

答案 0 :(得分:3)

QueryParam的默认行为是这样的:如果无法解码,则会出错,但是如果未指定,则返回Nothing。

从仆人0.13开始,您可以覆盖它。

如果您查看the definition of QueryParam,您会发现它实际上只是更一般的QueryParam'类型的一种特例:

type QueryParam = QueryParam' '[Optional, Strict]

QueryParam'采用了我们所说的“修饰符”,它影响两件事:

  • 您是否可以在没有该参数值的情况下生存:如果可以的话,您的处理程序将获得一个Maybe a,如果没有,您将直接获得一个a,但是如果没有给出任何值,它将出错。这是RequiredOptional
  • 您是否希望解码失败是致命的:如果您这样做,则解码失败时将为您显示仆人错误,否则您的处理程序将获得a。如果不这样做,那么处理程序会得到一个Either Text a,然后您可以自由地做任何您想做的事情,以防出现解码错误(这是Left的{​​{1}}情况,以及文字错误消息)。这是EitherStrict

因此,您可能想要定义类似Lenient之类的东西,并在适当的时候使用它。

能解决您的问题吗?