我本周末学习使用wreq而且我遇到了一些奇怪的行为。
我有一个模块AuthRequest
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DeriveGeneric #-}
module AuthRequest where
import Data.Aeson
import GHC.Generics
import Data.Monoid
data AuthRequest = AuthRequest {
client_id :: String
, client_secret :: String
, grant_type :: String
} deriving (Generic, Show)
instance ToJSON AuthRequest where
toJSON (AuthRequest id_ secret grant) =
object [ "client_id" .= id_
, "client_secret" .= secret
, "grant_type" .= grant
]
toEncoding(AuthRequest id_ secret grant) =
pairs ("client_id" .= id_ <> "client_secret" .= secret <> "grant_type" .= grant)
和模块HttpDemo
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DeriveGeneric #-}
module HttpDemo where
import Control.Lens
import Network.Wreq
import AuthRequest
import Data.Aeson
clientId = "some_id"
clientSecret = "some_secret"
url = "http://localhost:5000"
opts :: Options
opts = defaults
& header "Content-Type" .~ ["application/x-www-form-urlencoded"]
req :: AuthRequest
req = AuthRequest clientId clientSecret "credentials"
postIt = postWith opts url (toJSON req)
另一方面,我有一个简单的python烧瓶服务器,它使用断点监听此请求,以便我可以看到通过的值。
当我看到服务器端的request.form
时,我看到了:ImmutableMultiDict([('{"client_secret":"some_secret","client_id":"some_id","grant_type":"whatever"}', '')])
关键是我的帖子应该是什么!
但是如果我使用请求python库发出类似的请求
requests.post('http://localhost:5000', data={'client_id': clientId, 'client_secret': clientSecret, 'grant_type': grant_type}, headers={'content-type': 'application/x-www-form-urlencoded'})
我明白了我的期望:ImmutableMultiDict([('grant_type', 'whatever'), ('client_id', 'some_id'), ('client_secret', 'some_secret')])
我想我想要的是发送这个请求为x-www-form-urlencoded
。我看到有一些文档here围绕这个,但不清楚如何继续。也许我需要一个FormValue实例?一个例子会有所帮助。
根据您与@Alexis的讨论,您的客户端似乎正在发送JSON,而服务器预计是urlencoded。 Post
的文档显示了如何使用:=
构造函数发送urlencoded数据。在这种情况下,这将是
postIt = post url ["client_id" := clientId, "client_secret" := clientSecret, "grant_type" := grantType]
我使用post
而不是postWith
给出了这个例子,因为默认似乎是它使用application/x-www-form-urlencoded
。
似乎与OverloadedStrings
有轻微的并发症。为了制作可编译的程序,我不得不删除AuthRequest模块并明确地给出常量的类型,如下所示
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Network.Wreq
import Data.ByteString as B
clientId = "some_id" :: ByteString
clientSecret = "some_secret" :: ByteString
grantType = "credentials" :: ByteString
url = "http://localhost:8080"
postIt = post url ["client_id" := clientId, "client_secret" := clientSecret, "grant_type" := grantType]
main = postIt