R: Uploading binaries with curl package - r

I would like to port some code from RCurl to curl package to see if there is some efficiency gain.
Which is the equivalent of:
library(RCurl)
resp = postForm("https://httpbin.org/post", "fileData" = fileUpload(filename = "app.exe", contentType = "application/octet-stream"),
.opts = list(httpheader = c(Authorization = "token 123", `Content-Type` = "application/octet-stream")))
or
curl -H "Authorization: token 123" -H "Content-Type: application/octet-stream" --data-binary #app.exe "https://httpbin.org/post"
using the curl package?
BTW, this is what I tried:
library(curl)
h=new_handle()
handle_setform(h,
c(Authorization = "token 123", `Content-Type` = "application/octet-stream"),
fileData = form_file("app.exe", type="application/octet-stream")
)
req=curl_fetch_memory("http://httpbin.org/post", handle = h)

I need further testing, but this seems to be a general working upload solution:
library(curl)
h=new_handle()
handle_setheaders(h,
Authorization = "token 123",
"Content-Type" = "application/x-dosexec"
)
handle_setform(h,
app = form_file("app.exe", type="application/x-dosexec"))
req=curl_fetch_memory("http://httpbin.org/post", handle = h)

Related

422 error when submitting a POST request to REST API via R httr

I am trying to submit a POST request to a REST API (OpenET) in R.
The curl command below works successfully when run from the shell:
curl -X 'POST' \
'https://openet.dri.edu/timeseries/features/monthly' \
-H 'accept: application/json' \
-H 'Authorization: 'bla' \
-H 'Content-Type: application/json' \
-d '{
"feature_collection_name": "CA",
"field_ids": "[\"06324308\"]",
"model": "eemetric",
"variable": "et",
"start_date": "2021-01-01",
"end_date": "2022-12-31",
"output_format": "csv",
"units": "english"
}'
But this R code using httr returns an error 422: Unprocessable Entity (WebDAV; RFC 4918).
library(httr)
library(jsonlite)
api_key = 'bla'
url <- 'https://openet.dri.edu/timeseries/features/monthly'
request_body <- data.frame(
feature_collection_name = 'CA',
field_ids = "[\"06324308\"]",
model = 'eemetric',
variable = 'et',
start_date = '2021-01-01',
end_date = '2022-09-01',
units = 'english',
output_format = 'json')
request_body_json <- toJSON(request_body, pretty = T, autounbox = T)
response <- POST(url,
add_headers(`accept` = 'application/json',
`Authorization` = 'api_key',
`Content-Type` = 'application/json'),
body = request_body_json)
I have also tried specifying the headers differently:
response <- POST(url,
add_headers(accept = 'application/json',
Authorization = 'bla',
content_type = 'application/json'),
body = request_body_json)
I'd just like to know if I am using toJSON and POST correctly to reproduce the curl command above.

Converting a cURL command to HTTR in R

I have a cURL command that I would like to convert to R using the httr package. The cURL command looks something like this (I obviously can't post the full scope of it, given certain confidentiality restrictions):
curl --request POST \
--url https://api.cfb.com/v1/players/110960703/stats \
--header 'Accept: application/json' \
--header 'Authorization: Basic ThisIsWhereTheAPIKeyGoes==' \
--header 'Content-Type: application/json' \
--data '
{
"statsContext": {
"statsId": "1"
},
"responses": [
{
"type": "ReceiverStats",
"QuestionId": "466069",
"ResponseId": "1898226"
}
]
}
'
I would like to convert it to an HTTR script that looks like this:
ExportIdAPI <- POST(
'https://api.cfb.com/v1/players/110960703/stats',
accept_json(),
content_type_json(),
add_headers(Authorization = Basic ThisIsWhereTheAPIKeyGoes==),
encode = "json",
body=list(statsId = 1,
QuestionId = 466069,
ResponseId = 1898226))
The problem is, this script does not work. What does work is this script:
ExportIdAPI <- POST(
'https://api.cfb.com/v1/players/110960703/stats',
accept_json(),
content_type_json(),
add_headers(Authorization = Basic ThisIsWhereTheAPIKeyGoes==),
encode = "json",
body=list(statsId = 1))
Based on how the original curl request is structured, am I just not storing it right in the body=list statement?
EDIT: I should note that this script runs perfectly fine. I just don't want it to be structured that way and I would like it to better reflect the format I'm trying to achieve from above.
headers = c(
`Accept` = 'application/json',
`Authorization` = 'Basic ThisIsWhereTheAPIKeyGoes==',
`Content-Type` = 'application/json'
)
data = ' { "statsContext": { "statsId": "1" }, "responses": [ { "type": "SurveyResponse", "QuestionId": "466069", "ResponseId": "1898226" } ] } '
res <- httr::POST(url = 'https://api.cfb.com/v1/players/110960703/stats', httr::add_headers(.headers=headers), body = data)
EDIT 2: Based on MrFlick's response, I tried running:
ExportIdAPI <- POST(
'https://api.cfb.com/v1/players/110960703/stats',
accept_json(),
content_type_json(),
add_headers(Authorization = Basic ThisIsWhereTheAPIKeyGoes==),
encode = "json",
data = list(statsContext = list(statsId = 1), responses= list(list(type="SurveyResponse", QuestionId="466069", ResponseId="1898226")))
)
But I'm met with the following error:
Response [https://api.cfb.com/v1/players/110960703/stats]
Date: 2021-08-26 20:58
Status: 400
Content-Type: application/json; charset=utf-8
Size: 144 B
{
"errors": [
{
"code": "INVALID_PARAMETER",
"text": "The body of the request is null or cannot be parsed."
}
]
The httr documentation for the POST function provides an example for how to post a json.
In your case, you could really just copy the json of the cURL command to the body parameter of the POST function:
ExportIdAPI <- POST(
'https://api.cfb.com/v1/players/110960703/stats',
accept_json(),
content_type_json(),
add_headers(Authorization = 'Basic ThisIsWhereTheAPIKeyGoes=='),
body = '
{
"statsContext": {
"statsId": "1"
},
"responses": [
{
"type": "ReceiverStats",
"QuestionId": "466069",
"ResponseId": "1898226"
}
]
}', encode = "raw")
You can have the ROST() request format the JSON for you. As a general rule named lists are turned into JSON objects {} and unnamed list become arrays []. You can do
POST(
'https://api.cfb.com/v1/players/110960703/stats',
accept_json(),
content_type_json(),
add_headers(Authorization = "Basic ThisIsWhereTheAPIKeyGoes=="),
encode = "json",
body = list(
statsContext = list(
statsId = 1
),
responses= list(
list(
type="SurveyResponse",
QuestionId="466069",
ResponseId="1898226"
)
)
)
)

R POST API request with httr returns bad requests

Would like to implement the following POST request with curl with the httr package in R
curl 'https://api.openfigi.com/v2/mapping' \
--request POST \
--header 'Content-Type: application/json' \
--data '[{"idType":"ID_WERTPAPIER","idValue":"851399","exchCode":"US"}]'
Based on this Git issue I tried:
library(jsonlite)
library(rjson)
#>
#> Attaching package: 'rjson'
#> The following objects are masked from 'package:jsonlite':
#>
#> fromJSON, toJSON
library(httr)
url = 'https://api.openfigi.com/v2/mapping'
body1 = list(
idType = jsonlite::unbox('ID_WERTPAPIER'),
idValue = jsonlite::unbox('851399'),
exchCode = jsonlite::unbox('US')
)
r = httr::POST(url, body = body1, encode = 'json', verbose())
body2 = rjson::toJSON(list(
idType = "ID_WERTPAPIER",
idValue = "851399",
exchCode = "US"
))
r = httr::POST(url, body = body2, encode = "form", verbose())
Created on 2019-08-26 by the reprex package (v0.3.0)
But both are bad requests.
The following seems to work if you just translate the curl. Is that sufficient?
require(httr)
headers = c(
`Content-Type` = 'application/json'
)
data = '[{"idType":"ID_WERTPAPIER","idValue":"851399","exchCode":"US"}]'
r <- httr::POST(url = 'https://api.openfigi.com/v2/mapping', httr::add_headers(.headers=headers), body = data)
print(r$status_code)

How to use RCurl with the following parameters

I need to know how to write this parameters with RCurl:
curl -v -X PUT -H "X-IBM-Client-Secret:YOUR_CLIENT_SECRET" -H "X-IBM-Client-Id:YOUR_CLIENT_ID" -H "Content-Type: application/json" -d '{"clientName": "The Sample Outdoors Company", "redirectURIs": "https://example.com:5443", "ownerName": "John Smith", "ownerEmail": "John.Smith#example.com", "ownerCompany": "example.com", "ownerPhone": "555-123-4567"}' https://api.ibm.com/watsonanalytics/run/oauth2/v1/config
I really appreciate your help.
You can use it like this:
library(RCurl)
library(RJSONIO)
httpPUT("https://api.ibm.com/watsonanalytics/run/oauth2/v1/config",
content = toJSON(list('clientName' = "The Sample Outdoors Company", 'redirectURIs' = "https://example.com:5443", "ownerName" = "John Smith", "ownerEmail" = "John.Smith#example.com", "ownerCompany" = "example.com", "ownerPhone" = "555-123-4567")),
.opts = list(httpheader = c('Content-Type' = 'application/json', 'X-IBM-Client-Secret' = 'YOUR_CLIENT_SECRET', 'X-IBM-Client-Id' = 'YOUR_CLIENT_ID')))
Instead of toJSON you can pass just a string.

making specific request with httr

How would I make this request with httr?
'curl -X POST https://api.dropboxapi.com/2/files/list_folder \
--header "Authorization: Bearer 21318318usdhsdha9283718 " \
--header "Content-Type: application/json" \
--data "{\"path\": \"/today/\",\"recursive\": false,\"include_media_info\": false,\"include_deleted\": false}"'
I have tried using curlconverter but hasn't worked well for this one. I am not sure how I would go about implementing the --data parameter and what follows.
this works for me, does it work for you?
httr::POST(
"https://api.dropboxapi.com/2/files/list_folder",
add_headers(Authorization = "Bearer <token>"),
content_type_json(),
body = "{\"path\": \"/folder\",\"recursive\": false,\"include_media_info\": false,\"include_deleted\": false}",
encode = "json"
)
If you want to generalize a bit for many folders:
library("httr")
foobar <- function(x) {
content(POST(
"https://api.dropboxapi.com/2/files/list_folder",
add_headers(Authorization = "Bearer <token>"),
content_type_json(),
body = list(path = paste0("/", x), recursive = FALSE,
include_media_info = FALSE, include_deleted = FALSE),
encode = "json"
))
}
lapply(c('a', 'b', "c"), foobar)

Resources