所以,我有一个简单的Id类型:
newtype Id = Id String
deriving (Show, Eq, Ord, Generic)
instance ToJSON Id
instance FromJSON Id
instance FromHttpApiData Id where parseUrlPiece = Right . Id . Text.unpack
如此定义的仆人路线:
type SetEntryOrder = "entries" :> "order" :> ReqBody '[JSON] [Id] :> Post '[JSON] [Id]
我使用标题和请求正文向它发出请求,如下所示:
POST /entries/order HTTP/1.1
Host: localhost:9090
Connection: keep-alive
Content-Length: 199
Pragma: no-cache
Cache-Control: no-cache
Origin: http://localhost:9090
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36
Content-Type: application/json
Accept: */*
Referer: http://localhost:9090/
Accept-Encoding: gzip, deflate
Accept-Language: en
["0pAWSlIHH38sApt0n101X2brrCkyYp","1aaaaaaaaaaaaaaaaaaaaaaaaaaaaa","2aaaaaaaaaaaaaaaaaaaaaaaaaaaaa","7T84N81O7T84N81O7T84N81Obeu4JU","vMfOGs2LvMfOGs2LvMfOGs2LzjlQIP","j1Ew8Ju7HzAIv2yH9ohcdl9Wm2o7qx"]
但我带着以下身体返回400(路线根本没有输入):
Error in $: expected record (:*:), encountered Array
我克隆了github仆人回购并且为了这个的各个部分而慌张但是什么都没发现。
或许值得注意的是,我有很多其他路线可以正常工作。
我想也许我的Id
类型没有被正确解码(Aeson预期的记录或其他东西)但我可以使用同样的事情仆人在GHCI中没有问题:
> import Servant.API.ContentTypes (eitherDecodeLenient)
> eitherDecodeLenient "[\"hello\",\"hi\"]" :: Either String [Id]
Right [Id "hello",Id "hi"]
为我的Id类型定义自定义JSON处理程序,这样做不会有任何帮助:
instance ToJSON Id where
toJSON (Id s) = String $ Text.pack s
instance FromJSON Id where
parseJSON (String s) = return $ Id $ Text.unpack s
parseJSON _ = empty
Sooo,有没有人知道为什么Servant试图解码我的Ids阵列并给我400而不是进入我的路线? :)
版本
堆叠LTS 6.15,意思是:
GHC 7.10.3,仆人0.7.1,仆人服务器0.7.1,aeson 0.11.2.1
(我测试过servant-0.8.1但也没有变化)
原始代码
https://github.com/jsdw/talklicker/tree/master/server(路由定义见Routes.hs,Id定义见Types.hs)
所以,问题似乎是仆人正在匹配错误的路线,就像将正确的数据传递到我的/entries/orders
路线一样(事实上,似乎我可以替换"命令"使用任何字符串,并且尾随斜杠没有区别!),我实际上可以进入/entries
路由。将另一个路径段(例如:> "dadada"
)添加到SetEntryOrder并使用它可以让我定位正确的路线。
有问题的重叠路线是:
type SetEntryOrder = HasSession :> "order" :> ReqBody '[JSON] [Id] :> Post '[JSON] [Id]
和
type AddEntry = HasSession :> ReqBody '[JSON] AddEntryInput :> Post '[JSON] Entry
注意到这两个都以"条目"为前缀。在我的Routes.hs文件的顶部。我还没有弄清楚为什么会这样,但这只是一个开始!
问题解决了!它实际上是因为我有重叠的路线,所以我的错!我为自己做了一些努力,因为重叠的路线几乎接受了任何输入(但我忘记了!)。交换路线固定它。