(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.)