Converting a cURL command to HTTR in R - 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"
)
)
)
)

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.

AWS API in R - Added Authorization Header but getting InvalidSignatureException

I am trying to use AWS API in R. I am using R so that i can add it to an exisiting ShinyApp (which is a web application build in R).
This API: https://docs.aws.amazon.com/connect/latest/APIReference/API_GetCurrentMetricData.html
Using signature version 4:
https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html
I have added the 'Authorization' details to the header as per AMZ documentation, and the exact header works perfectly in python, but strangely not in R and returns an error saying 'InvalidSignatureException'.
My guess is that i have got something wrong with the variables in the POST function. I've quite a few different arrangements of the POST variables to try and get it to work but nothing seems to help.
This is the python code which works:
import requests
url = "https://connect.eu-central-1.amazonaws.com/metrics/current/XXXXXXX"
payload = "{\r\n \"InstanceId\" : \"XXXXXXX\",\r\n \"Filters\" : {\r\n \"Queues\" : [\r\n \"XXXXXXX\",\r\n \"arn:aws:connect:eu-central-1:XXXXXXX:instance/XXXXXXX/queue/XXXXXXX\"\r\n ]\r\n },\r\n \"CurrentMetrics\" : [\r\n {\r\n \"Name\" : \"AGENTS_ONLINE\",\r\n \"Unit\" : \"COUNT\"\r\n },\r\n {\r\n \"Name\" : \"AGENTS_AVAILABLE\",\r\n \"Unit\" : \"COUNT\"\r\n },\r\n {\r\n \"Name\" : \"OLDEST_CONTACT_AGE\",\r\n \"Unit\" : \"SECONDS\"\r\n },\r\n {\r\n \"Name\": \"AGENTS_ERROR\",\r\n \"Unit\": \"COUNT\"\r\n }\r\n ]\r\n}\r\n "
headers = {
'Content-Type': "application/json",
'X-Amz-Content-Sha256': "XXXXXXX",
'Host': "connect.eu-central-1.amazonaws.com",
'X-Amz-Date': "20190724T162517Z",
'Authorization': "AWS4-HMAC-SHA256 Credential=XXXXXXX/20190724/eu-central-1/connect/aws4_request, SignedHeaders=content-type;host;x-amz-content-sha256;x-amz-date, Signature=XXXXXXX",
}
response = requests.request("POST", url, data=payload, headers=headers)
print(response.text)
My attempt to write in R. (returns x-amzn-ErrorType: InvalidSignatureException)
library(httr)
library(jsonlite)
request_body_json <-
'{
"InstanceId" : "xxxxxxxxxx",
"Filters" : {
"Queues" : [
"xxxxxxxxxx",
"arn:aws:connect:eu-central-1:xxxxxxxxxx:instance/xxxxxxxxxx/queue/xxxxxxxxxx"
]
},
"CurrentMetrics" : [
{
"Name" : "AGENTS_ONLINE",
"Unit" : "COUNT"
},
{
"Name" : "AGENTS_AVAILABLE",
"Unit" : "COUNT"
},
{
"Name" : "OLDEST_CONTACT_AGE",
"Unit" : "SECONDS"
},
{
"Name": "AGENTS_ERROR",
"Unit": "COUNT"
}
]
}'
hdrs <- list(
'Content-Type'= "application/json",
'X-Amz-Content-Sha256'= "XXXXXXX",
'Host'= "connect.eu-central-1.amazonaws.com",
'X-Amz-Date'= "20190724T162517Z",
'Authorization'= "AWS4-HMAC-SHA256 Credential=XXXXXXX/20190724/eu-central-1/connect/aws4_request, SignedHeaders=content-type;host;x-amz-content-sha256;x-amz-date, Signature=XXXXXXX"
)
a <- POST(
url = "https://connect.eu-central-1.amazonaws.com/metrics/current/xxxxxxxxxx"
,do.call(add_headers,hdrs)
,verbose(info = TRUE)
,body = request_body_json
,encode = "json"
)
Fixed and added the authorisations steps in too.
# Librarys used
library(httr)
library(jsonlite)
library(aws.signature)
#gather variables
host <- "connect.eu-central-1.amazonaws.com"
sha <- "xxxx"
amzdate <- format(Sys.time(), "%Y%m%dT%H%M%SZ",tz = "UTC")
payload <-
'{
"InstanceId" : "xxxx-xxxx-xxxx-xxxx-xxxx",
"Filters" : {
"Queues" : [
"xxxx-xxxx-xxxx-xxxx"
]
},
"CurrentMetrics" : [
{
"Name" : "OLDEST_CONTACT_AGE",
"Unit" : "SECONDS"
},
{
"Name": "CONTACTS_IN_QUEUE",
"Unit": "COUNT"
}
]
}'
content_type <-"application/json"
url_api <-"https://connect.eu-central-1.amazonaws.com/metrics/current/xxxx-xxxx-xxxx-xxxx"
region <- "eu-central-1"
service <- "connect"
verb <- "POST"
action <- "/metrics/current/xxxx-xxxx-xxxx-xxx-xxxx"
key <- "xxxx"
secret <- "xxxx"
#headers so far (can't add signature yet)
hdrs <- list('Content-Type' = content_type,
Host = host,
'x-amz-content-sha256' = sha,
'x-amz-date' = amzdate)
#get v4 signature
sig <- signature_v4_auth(datetime = amzdate,
region = region,
service = service,
verb = verb,
action = action,
query_args = list(),
canonical_headers = hdrs,
request_body = payload,
key = key,
secret = secret,
session_token = NULL,
query = FALSE,
algorithm = "AWS4-HMAC-SHA256")
#add signature header to header
auth <- sig$SignatureHeader
a <- httr::VERB(verb = "POST"
,url = url_api
,encode = 'json'
,content_type_json()
,body = payload
,httr::add_headers(
'Content-Type' = content_type,
Authorization = auth,
Host = host,
`X-Amz-Content-Sha256` = sha,
`X-Amz-Date` = amzdate)
)
results <- content(a,"parsed")

R: Uploading binaries with curl package

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)

How to Post API in R having header & json body

How to call API Post in R
Request URL
https://westus.api.cognitive.microsoft.com/text/analytics/v2.0/sentiment
Request headers
Ocp-Apim-Subscription-Key = some value &
Content-Type = application/json
Body application/json
{
"documents": [
{
"language": "string",
"id": "string",
"text": "string"
}
]
}
Please help!!!
Here is the example -
request_body <- data.frame(
language = c("en","en"),
id = c("1","2"),
text = c("This is wasted! I'm angry","This is awesome! Good Job Team! appreciated")
)
Converting the Request body(Dataframe) to Request body(JSON)
require(jsonlite)
request_body_json <- toJSON(list(documents = request_body), auto_unbox = TRUE)
Below we are calling API (Adding Request headers using add_headers)
require(httr)
result <- POST("https://westus.api.cognitive.microsoft.com/text/analytics/v2.0/sentiment",
body = request_body_json,
add_headers(.headers = c("Content-Type"="application/json","Ocp-Apim-Subscription-Key"="my_subscrition_key")))
Output <- content(result)
Show Output
Output

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