Search code examples
httphaskellputhttp-putwreq

How to send a PUT request with wreq?


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?


Solution

  • 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.