Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add non-binary file list option to make_form? #93

Closed
ampu3ro opened this issue Mar 9, 2017 · 10 comments
Closed

Add non-binary file list option to make_form? #93

ampu3ro opened this issue Mar 9, 2017 · 10 comments

Comments

@ampu3ro
Copy link

ampu3ro commented Mar 9, 2017

This is more of a question than a request, as I may just be missing something...

I think it might be useful to be able to define the content-type for a non-binary element of a multipart form. Basically, I have this issue with binary & non-binary parts and I have a hunch that defining an intermediate case in make_form could do the trick:

curl_formadd(&post, &last, CURLFORM_COPYNAME, name, CURLFORM_COPYCONTENTS, body, CURLFORM_CONTENTTYPE, content_type, CURLFORM_END);

The idea is that I could pass a string with a defined content-type (similar to the second example here):

url <- "https://my_salesforce_instance/services/data/v39.0/sobjects/Document/"
header <-  httr::add_headers("my_salesforce_auth")

x <- data.frame(FolderId="a0a1300000ZG7u3",Name="test1.png")
json <- jsonlite::toJSON(unbox(x),pretty=T)
doc <- list(body=json,content_type="application/json")

tmp <- tempfile(fileext=".png")
png(tmp)
plot(mtcars)
dev.off()
body <- httr::upload_file(tmp)

httr::POST(url,header,body=list(entity_document=doc,Body=body),encode="multipart",verbose())

I couldn't get a local build of curl with this tweak to work, but I'm not at all confident writing C code. On the other hand this may not even be relevant to solve the issue. Any suggestions?

@jeroen
Copy link
Owner

jeroen commented Mar 9, 2017

Did you read the section on posting forms from the vignette? The curl::form_file function allows you to specify a content type. Perhaps you can use this?

@jeroen
Copy link
Owner

jeroen commented Mar 9, 2017

Hmm reading the SO, maybe I don't fully understand the question. Let me look into it better.

@ampu3ro
Copy link
Author

ampu3ro commented Mar 9, 2017

Thanks for the quick reply. Yeah, I think what I'm describing is something between a simple character like foo, which is handled with

curl_formadd(&post, &last, CURLFORM_COPYNAME, name, CURLFORM_COPYCONTENTS, translateCharUTF8(asChar(val)), CURLFORM_END);

and a form file like logo which is handled with

curl_formadd(&post, &last, CURLFORM_COPYNAME, name, CURLFORM_FILE, path, CURLFORM_CONTENTTYPE, content_type, CURLFORM_END);

As mentioned above, I'm not even sure this will solve the problem so if you have any other ideas I'm open to them! Thanks

@jeroen
Copy link
Owner

jeroen commented Mar 9, 2017

I don't think there is a distinction between binary and non-binary data inside a multipart body. I think --data-binary simply means that you want to use multipart encoding.

Only multipart encoding supports setting a content type, from your example:

>> Content-Disposition: form-data; name="y"; filename="db_biggest_tables.csv"
>> Content-Type: application/octet-stream

If you post a x-www-form-urlencoded body, values simply get turned into a val=foo&val2=bar string so there is no way to specify a content type. Everything is just a string.

So I'm not sure what exactly it is that you want, but from your SO post it kind of looks like a bug on in the salesforge API?

@ampu3ro
Copy link
Author

ampu3ro commented Mar 9, 2017

I guess, more to the point, I'm wondering if the multipart body could have a part with the header

>> Content-Disposition: form-data; name="entity_document"
>> Content-Type: application/json

This doesn't seem possible with curl because I can only get

>> Content-Disposition: form-data; name="entity_document"; filename="file1510059b5200f"
>> Content-Type: application/json

if I use form_file (technically httr::upload_file) or

>> Content-Disposition: form-data; name="entity_document"

if I POST the json/character directly.

It's certainly possible that Salesforce API has a bug, it just seems unlikely to me given how many organizations use it and how this operation is documented.

@jeroen
Copy link
Owner

jeroen commented Mar 9, 2017

OK I get it now. You want to set a Content-Type but not a filename for a given field?

@ampu3ro
Copy link
Author

ampu3ro commented Mar 9, 2017

Yep! Sorry that wasn't very clear before. Do you think that might solve the issue? It's the only obvious mismatch I can see between Salesforce's example and mine. I can also imagine that functionality would be useful more generally, but I don't know enough about Curl to have a good sense.

@jeroen
Copy link
Owner

jeroen commented Mar 9, 2017

OK I have added a new function form_data which allows you to post a string or raw vector with a custom content type. Can you give this a try? To install the dev version of curl in a clean R session:

install.packages("https://github.com/jeroenooms/curl/archive/master.tar.gz", repos = NULL)

And then look at ?form_data

@ampu3ro
Copy link
Author

ampu3ro commented Mar 9, 2017

Beautiful! Worked like a charm. I really appreciate the help and speed in execution

@ampu3ro
Copy link
Author

ampu3ro commented Mar 9, 2017

Just closing the loop, httr::body_config will need updating in order work with this enhancement. Happy to post an issue on that repo tomorrow. Thanks again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants