给出以下代码:
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。现在,我要更改问题。如果发生这种情况,如何返回自定义错误消息?
的默认行为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]并在适当的时候使用它。
这样可以解决您的问题吗?