3
$\begingroup$

(orig: URLFetch Multipart POST fails to post Body?)

Update 2:

So after much weeping and gnashing of teeth Mathematica deemed me worthy of figuring out (some of) what was going on.

It turns out the body was being passed okay (or the multipart elements were, at least, which it turns out is sufficient). I was thrown for a loop because the "Parameters" argument of URLFetch was interfering with either the "Body" or "Headers" of my post call.

As an example I was doing a Google Drive upload and it looked like:

URLFetch[apiBase?uploadType=multipart,
  "Method"->"POST",
  "Parameters"->{uploadType->"multipart","access_token"-><MY_TOKEN>},
  "MultipartElements"->{
   {"metadata","application/json"}-><METADATA_BYTES>,
   {"contentdata","text/plain"}-><CONTENTDATA_BYTES>
   }
  ]

And that "Parameters" interfered with something. By pushing the "access_token" into the "Authorization" header and removing the "Parameters" field altogether I finally got it to work.

Update:

It turns out this might be a more general issue just with my setup as it fails for HTTPRequest too:

In[1122]:= Import@
 HTTPRequest[url,
  <|
   "Method" -> "Post",
   "Body" -> 
    "--divider-b1cd97ef-a024-40ae-92ea-e296812bfbdc\nContent-Type: \
application/json\n\n{\n    \"name\": \"test.txt\"\n}\n\
--divider-b1cd97ef-a024-40ae-92ea-e296812bfbdc\nContent-Type: \
application/vnd.wolfram.mathematica.package\n\ntest string\n\
--divider-b1cd97ef-a024-40ae-92ea-e296812bfbdc--", 
   "Headers" -> {"Content-Type" -> 
      "multipart/related; \
boundary=divider-b1cd97ef-a024-40ae-92ea-e296812bfbdc", 
     "Content-Length" -> "272"}
   |>
  ]

Out[1122]= "{\"POST\", {\"host\" -> \"www.wolframcloud.com\", \
\"accept\" -> \"*/*\", \"content-type\" -> \"multipart/related; \
boundary=divider-b1cd97ef-a024-40ae-92ea-e296812bfbdc\", \"user-agent\
\" -> \"Wolfram HTTPClient 11.1\", \"x-forwarded-proto\" -> \
\"https\", \"x-forwarded-for\" -> \"76.118.178.116, 10.11.32.157\", \
\"x-forwarded-host\" -> \"www.wolframcloud.com\", \
\"x-forwarded-server\" -> \"www.wolframcloud.com\", \
\"content-length\" -> \"272\"}, None, Missing[\"NotAvailable\"]}"

So maybe something more subtle is going on with my API call.


Original:

The service connection framework uses URLFetch to do its dirty-work and so I am stuck using that too.

Unfortunately for multipart uploads there's something bizarro going on. Consider the following:

url = First@
 CloudDeploy[
  Delayed[HTTPRequestData[{"Method", "Headers",
      "Body"}], "WL"]];

In[631]:= ToExpression@
 URLFetch[url,
  "MultipartElements" -> {{"metadata", "application/json"} -> {123, 
      10, 32, 32, 32, 32, 34, 110, 97, 109, 101, 34, 58, 32, 34, 116, 
      101, 115, 116, 46, 116, 120, 116, 34, 10, 125}, {"contentdata", 
      "application/vnd.wolfram.mathematica.package"} -> {116, 101, 
      115, 116, 32, 115, 116, 114, 105, 110, 103}},
  "Method" -> "POST",
  "CredentialsProvider" -> None
  ]

Out[631]= {"POST", {"host" -> "www.wolframcloud.com", 
  "user-agent" -> "Wolfram HTTPClient 11.1", "accept" -> "*/*", 
  "expect" -> "100-continue", 
  "content-type" -> 
   "multipart/form-data; \
boundary=------------------------7271f99252c452e1", 
  "x-forwarded-proto" -> "https", 
  "x-forwarded-for" -> "76.118.178.116, 10.11.32.157", 
  "x-forwarded-host" -> "www.wolframcloud.com", 
  "x-forwarded-server" -> "www.wolframcloud.com", 
  "content-length" -> "371"}, Missing["NotAvailable"]}

Notice that the "Body" element is missing. For some reason the "POST" call didn't the multipart-encoded stuff.

On the other hand:

In[632]:= ToExpression@
 URLFetch[url,
  "MultipartElements" -> {{"metadata", "application/json"} -> {123, 
      10, 32, 32, 32, 32, 34, 110, 97, 109, 101, 34, 58, 32, 34, 116, 
      101, 115, 116, 46, 116, 120, 116, 34, 10, 125}, {"contentdata", 
      "application/vnd.wolfram.mathematica.package"} -> {116, 101, 
      115, 116, 32, 115, 116, 114, 105, 110, 103}},
  "Method" -> "GET",
  "CredentialsProvider" -> None
  ]

Out[632]= {"GET", {"host" -> "www.wolframcloud.com", 
  "user-agent" -> "Wolfram HTTPClient 11.1", "accept" -> "*/*", 
  "expect" -> "100-continue", 
  "content-type" -> 
   "multipart/form-data; \
boundary=------------------------2e317ef0d18c6ab7", 
  "x-forwarded-proto" -> "https", 
  "x-forwarded-for" -> "76.118.178.116, 10.11.32.157", 
  "x-forwarded-host" -> "www.wolframcloud.com", 
  "x-forwarded-server" -> "www.wolframcloud.com", 
  "content-length" -> 
   "371"}, "--------------------------2e317ef0d18c6ab7

 Content-Disposition: form-data; name=\"metadata\"

 Content-Type: application/json



 {
     \"name\": \"test.txt\"
 }

 --------------------------2e317ef0d18c6ab7

 Content-Disposition: form-data; name=\"contentdata\"

 Content-Type: application/vnd.wolfram.mathematica.package



 test string

 --------------------------2e317ef0d18c6ab7--

 "}

That seems to work fine. So the "GET" request was okay but the "POST" one failed.

Is there a reason for this? Is there a way around it?

(Note that this is an for met issue even though the "MultipartElements" field of the HTTPRequestData encodes correctly. The Google Drive upload API endpoint notices an empty "Body" and throws an error.)

$\endgroup$
  • $\begingroup$ I've found Mathematica HTTP handling to be mostly straightforward and occasionally byzantine, as in this case. So thanks for posting your solution! $\endgroup$ – Paul Clip Jun 8 '17 at 0:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.