2017-05-13 10 views
0

今週末にwreqを使用する方法を学んでいます。wreqでx-www-form-urlencodedのコンテンツタイプとしてリクエストを送信

Iモジュール他端に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のフラスコサーバを有します来る価値を見てください。 ImmutableMultiDict([('{"client_secret":"some_secret","client_id":"some_id","grant_type":"whatever"}', '')])

キーは私のポスト本体がどうあるべきかです:私は、サーバー側でrequest.formを見てみると

は、私はこの参照してください!

しかし、私は

requests.post('http://localhost:5000', data={'client_id': clientId, 'client_secret': clientSecret, 'grant_type': grant_type}, headers={'content-type': 'application/x-www-form-urlencoded'}) 

要求のPythonライブラリを使用して、同様の要求をする場合、私は私が期待するものを見る:ImmutableMultiDict([('grant_type', 'whatever'), ('client_id', 'some_id'), ('client_secret', 'some_secret')])

私は私がしたいと思う何がx-www-form-urlencodedとして、この要求を送信することです。私はこれの周りにいくつかのドキュメントhereが表示されますが、続行する方法については明確ではありません。多分私はFormValueインスタンスが必要でしょうか?例が役に立ちます。

+0

以下のように定数の型を与えなければならなかった'アプリケーション/ x-www-form-urlencoded'とは完全に異なるエンコーディングです。 –

+0

@AlexisKing最終的に私がこのリクエストでターゲットとしているアプリケーションでは、urlencode形式が必要です。だから、どうすればいいのでしょうか?私は、どのようにPythonリクエストが送信しているものと一致するように、URLエンコードされたデータを送信するのですか? – munk

+1

はい、ここは正しい質問のようです。サーバーがフォームデータを期待している場合、JSONの送信は機能しません。 –

答えて

1

@Alexisとのディスカッションによれば、クライアントはJSONを送信しているようですが、サーバーはurlencodedされています。 Postのドキュメントは、:=コンストラクタを使用して、urlencodedデータを送信する方法を示しています。この場合、これはデフォルトでは、それがapplication/x-www-form-urlencodedを使用しているように見えるので、私はpostではなくpostWithを使用した例を与えてくれた

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

だろう。


OverloadedStringsとちょっとした合併症があるようです。コンパイルプログラムを作るために、私はあなたのコンテンツタイプがアプリケーション/ json`、ではない `する必要があります、てauthrequestモジュールを削除し、JSONを送信する場合は、明示的に

{-# 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 
関連する問題