Servant QueryParams解析错误

aut*_*322 3 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
Run Code Online (Sandbox Code Playgroud)

我可以访问/hello哪个返回{ "msg" : 0}/hello?age=20哪个返回{ "msg" : 20}。但是,如果我将年龄设置为非整数可解析的(例如"foobar",使网址成为/hello?age=foobar并可以访问它),它将返回有关解析错误on的错误消息"foobar"

Capture如果我给予相同的处理,它将返回一个http 400,这在行为上有所不同。

我的代码有什么问题?

编辑:进一步探索后,它的解析错误确实返回http 400。现在,我要更改问题。如果发生这种情况,如何返回自定义错误消息?

Alp*_*ari 5

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

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

如果查看的定义QueryParam,您会发现它实际上只是更通用QueryParam'类型的一种特殊情况:

type QueryParam = QueryParam' '[Optional, Strict]
Run Code Online (Sandbox Code Playgroud)

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

  • 是否可以在没有该参数值的情况下生存:如果可以,则处理程序将获取一个Maybe a,如果不是,则直接获取一个,a但是在未指定任何值时会出错。这是RequiredVS Optional
  • 是否希望解码失败是致命的:如果这样做,则解码失败时将为您显示仆人错误,否则处理程序将收到a。如果您不这样做,则处理程序将得到一个,然后您Either Text a可以自由地做任何您想做的事情,以防出现解码错误(Left对于Either带有文本错误消息的,就是这种情况)。这是StrictVS Lenient

因此,您可能想定义类似的东西,type MyQueryParam name a = QueryParam' '[Optional, Lenient]并在适当的时候使用它。

这样可以解决您的问题吗?