Here is how I would expect to be able to send a PUT request with wreq
:
{-# LANGUAGE OverloadedStrings #-}
import Network.Wreq
main = put "http://httpbin.org/put" ["foo":=(1::Int)]
However, this gives the following error:
HttpExceptionRequest Request {
host = "httpbin.org"
port = 80
secure = False
requestHeaders = [("Content-Type","application/x-www-form-urlencoded"),("User-Agent","haskell wreq-0.5.3.2")]
path = "/put"
queryString = ""
method = "POST"
proxy = Nothing
rawBody = False
redirectCount = 10
responseTimeout = ResponseTimeoutDefault
requestVersion = HTTP/1.1
}
(StatusCodeException (Response {responseStatus = Status {statusCode = 405, statusMessage = "METHOD NOT ALLOWED"}, responseVersion = HTTP/1.1, responseHeaders = [("Date","Fri, 07 Feb 2020 19:26:28 GMT"),("Content-Type","text/html"),("Content-Length","178"),("Connection","keep-alive"),("Server","gunicorn/19.9.0"),("Allow","PUT, OPTIONS"),("Access-Control-Allow-Origin","*"),("Access-Control-Allow-Credentials","true")], responseBody = (), responseCookieJar = CJ {expose = []}, responseClose' = ResponseClose}) "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n<title>405 Method Not Allowed</title>\n<h1>Method Not Allowed</h1>\n<p>The method is not allowed for the requested URL.</p>\n")
As is evident from the error message,
wreq
appears to be sending a POST request instead,
despite the fact that I used the put
method.
How can I get wreq
to actually send a PUT request?
I believe the issue is that if you try to put
using a [FormParam]
, the method gets overridden and changed to POST
. If you put
a different kind of payload:
main = put "http://httpbin.org/put" ("xyz" :: ByteString)
then it works fine:
Response {responseStatus = Status {statusCode = 200, statusMessage = "OK"}, ...
I believe this is a limitation/intentional design decision in the underlying http-client
package that wreq
uses. When the function urlEncodedBody
is used to pack form data into the body, it has the side effect of changing the method of the request to POST
.