I'm learning to use wreq this weekend and I've run into some strange behavior.
I have a module 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)
and a module 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)
On the other end, I have a simple python flask server that listens to this request with a breakpoint so I can see the value that comes through.
When I look at the request.form
on the server side, I see this: ImmutableMultiDict([('{"client_secret":"some_secret","client_id":"some_id","grant_type":"whatever"}', '')])
The key is what should be my post body!
But if I make a similar request using the requests python library
requests.post('http://localhost:5000', data={'client_id': clientId, 'client_secret': clientSecret, 'grant_type': grant_type}, headers={'content-type': 'application/x-www-form-urlencoded'})
I see what I expect: ImmutableMultiDict([('grant_type', 'whatever'), ('client_id', 'some_id'), ('client_secret', 'some_secret')])
What I think I want is to send this request as x-www-form-urlencoded
. I see there are some docs here around this, but not clear on how to proceed. Maybe I need a FormValue instance? An example would be helpful.
As per your discussion with @Alexis, your client seems to be sending JSON, while the server is expected urlencoded. The documentation of
Post
shows how to send urlencoded data, using the:=
constructor. In this case this would beI've given the example using
post
rather thanpostWith
since the default appears to be that it usesapplication/x-www-form-urlencoded
.There seems to be a slight complication with
OverloadedStrings
. To make a compilable program, I had to remove the AuthRequest module and explicitly give the types of the constants as below