0

这个周末我正在学习使用 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"}', '')])

关键是我的帖子正文应该是什么!

但是,如果我使用 requests 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. 我看到这里有一些文档,但不清楚如何进行。也许我需要一个 FormValue 实例?一个例子会很有帮助。

4

1 回答 1

2

根据您与@Alexis 的讨论,您的客户端似乎正在发送 JSON,而服务器预计是 urlencoded。的文档Post显示了如何使用:=构造函数发送 urlencoded 数据。在这种情况下,这将是

postIt = post url ["client_id" := clientId, "client_secret" := clientSecret, "grant_type" := grantType]

我给出了示例 usingpost而不是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
于 2017-05-14T18:02:22.647 回答