1

だから、私は単純な 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 サーバント リポジトリのクローンを作成し、さまざまな部分を grep しましたが、何も見つかりませんでした。

うまく機能する他のルートがたくさんあることは、おそらく注目に値するでしょう。

おそらく私の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

すっごく、なぜ Servant が Id の配列をデコードしようとして立ち往生し、私のルートに入るのではなく 400 をスローするのか、誰にもわかりませんか? :)

バージョン

スタック LTS 6.15、つまり:

GHC 7.10.3、サーバント 0.7.1、サーバント サーバ 0.7.1、エイソン 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 ファイルの先頭で、これらの両方に「エントリ」というプレフィックスが付いていることに注意してください。なぜこれが事実なのかはまだわかりませんが、それは始まりです!

アップデート2!

問題が解決しました!実はルートが重複していたので、私のせいです!重複するルートはほとんどすべての入力を受け入れるので、私は自分で物事を難しくしました(しかし、これを忘れていました!)。ルートを交換すると修正されました。

4

0 に答える 0