I am adding a page to a website through REST API. I use the following in bash and it works. It creates a new page with the specified title and body content.
token="dfrer4e"
curl -X POST -H "Authorization: Bearer $token" \
https://api/pages \
-d wiki_page[title]=New title \
-d wiki_page[body]=New content
I am trying to do the same using R package httr.
library(httr)
set_config(add_headers("Authorization"=paste0("Bearer dfrer4e")))
This works when I just use the title. It creates a new page with the specified title.
POST(url="https://api/pages/",body="wiki_page[title]=New title")
but I am not sure how to include the body part as well.
Attempts:
I tried providing the body as a vector, but it doesn't work correctly. It combines both into the title. The body remains empty.
POST(url="https://api/pages/",body=c("wiki_page[title]=New page","wiki_page[body]=New content"))
I tried providing the body as a list, but it returns an error.
POST(url="https://api/pages/",body=list("wiki_page"=list("title"="New title","body"="New content")))
Error in curl::handle_setform(handle, .list = req$fields) :
Unsupported value type for form field 'wiki_page'.
I tried to provide the body as JSON, but it returns a status 400 error.
j <- jsonlite::toJSON(list("wiki_page"=list("title"="New title","body"="New content")))
POST(url="https://api/pages/",body=j,encode="json")
Unfortunately, I cannot create a reproducible example.
The proper way to translate that command to httr is
POST(url="https://api/pages/",
body=list(
"wiki_page[title]" = "New page",
"wiki_page[body]" = "New content")
)
You need to separate the names and the values in your body so the values can be properly encoded.
Related
I am currently writing a webhook on a heroku server and for some reason I am having difficulty obtaining the values stored in the body of the request as it always seems to turn up as NULL. My app.R script looks like all those in the guides:
#app.R
library(plumber)
library(tidyverse)
port <- Sys.getenv('PORT')
pr <- plumb("plumber.R")
pr$run(
host = '0.0.0.0',
port = as.numeric(port)
)
My plumber.R file starts like this.
library(plumber)
library(tidyverse)
#* Log some information about the incoming request
#* #filter logger
function(req){
print('LOGGER')
print( req)
cat(as.character(Sys.time()), "-",
req$REQUEST_METHOD, req$PATH_INFO, "-",
req$HTTP_USER_AGENT, "#", req$REMOTE_ADDR, "\n")
plumber::forward()
}
#* #filter bodyExists?
function(req, res){
print( 'BODY FILTER')
print( req$body)
if (is.null(req$body)){
res$status <- 404
return(list(error="Body not found"))
} else {
plumber::forward()
}
}
Every time it receives a request the console shows out this:
And stops because there is no body. I have tried sending it requests from multiple sources where I know a body is being sent with the request but for some reason plumber does not find it when it reaches my api. I have been following using https://github.com/virtualstaticvoid/heroku-plumber-app as a template and I don't see what Im doing different from them.
Was supposed to use req$postBody rather than req$body
Plumber should be able to parse the body of the post request automatically unless the content type is incorrect or unspecified.
In my case, I had forgotten to specify the content type header of the request (I tested the API using curl from the command line). Once I set it to -H "Content-Type: application/json", plumber was able to parse the body correctly and I could see the payload in req$body as well as req$args.
If you decide to use req$postBody, like the OP did, note that as of plumber v1.0.0 it is recommended to use req$bodyRaw rather than req$postBody. For more information, see postBody in the plumber request object as well as plumber PR#665.
I am trying to get data from IMDB with
page <- read_html("URL_of_Movie")
The output is always in German. However, I need the data content to be in its original form in English. Although my settings are set to "English"
I saw others Questions here like this
curl -H "Accept-Language: en-us,en;q=0.8,de-de;q=0.5,de;q=0.3" http://www.imdb.com/title/tt0076306/
which shows how to use curl function for english but I don't know how to integrate this into my R code
Needed to include the GET Function and the correct Syntax for the language request
page <- read_html(GET(
"https://www.imdb.com/list/ls020643534/?sort=list_order,asc&st_dt=&mode=detail&page=1&title_type=movie&ref_=ttls_ref_typ",
add_headers("Accept-Language" = "en-US")))
I have this working curl statement to post a file to Nokia's HERE batch geocoding service...
curl -X POST -H 'Content-Type: multipart/form-data;boundary=----------------------------4ebf00fbcf09' \
--data-binary #example.txt \
'http://batch.geocoder.cit.api.here.com/6.2/jobs?action=run&mailto=test#gmail.com&maxresults=1&language=es-ES&header=true&indelim=|&outdelim=|&outcols=displayLatitude,displayLongitude,houseNumber,street,district,city,postalCode,county,state,country,matchLevel,relevance&outputCombined=false&app_code=AJKnXv84fjrb0KIHawS0Tg&app_id=DemoAppId01082013GAL'
I have tried this:
library(RCurl)
url <- "http://batch.geocoder.cit.api.here.com/6.2/jobs? action=run&mailto=test#gmail.com&maxresults=1&language=es-ES&header=true&indelim=|&outdelim=|&outcols=displayLatitude,displayLongitude,houseNumber,street,district,city,postalCode,county,state,country,matchLevel,relevance&outputCombined=false&app_code=AJKnXv84fjrb0KIHawS0Tg&app_id=DemoAppId01082013GAL'"
postForm(url, file=fileUpload(filename="example.txt",
contentType="multipart/form-data;boundary=----------------------------4ebf00fbcf09"))
And this:
library(httr)
a <- POST(url, body=upload_file("example.txt", type="text/plain"),
config=c(add_headers("multipart/form-data;boundary=----------------------------4ebf00fbcf09")))
content(a)
Using this file as example.txt: https://gist.github.com/corynissen/4f30378f11a5e51ad9ad
Is there any way to do this property in R?
I'm not a Nokia developer, and I'm assuming those are not your real API creds. This should help you get further with httr:
url <- "http://batch.geocoder.cit.api.here.com/6.2/jobs"
a <- POST(url, encode="multipart", # this will set the header for you
body=list(file=upload_file("example.txt")), # this is how to upload files
query=list(
action="run",
mailto="test#example.com",
maxresults="1",
language="es-ES", # this will build the query string
header="true",
indelim="|",
outdelim="|",
outcols="displayLatitude,displayLongitude", # i shortened this for the example
outputCombined="false",
app_code="APPCODE",
app_id="APPID"),
verbose()) # this lets you verify what's going on
But, I can't be sure w/o registering (and no time to do that).
This is the solution based on hrbrmstr's solution
bod <- paste(readLines("example.txt", warn=F), collapse="\n")
a <- POST(url, encode="multipart", # this will set the header for you
body=bod, # this is how to upload files
query=list(
action="run",
mailto="test#gmail.com",
maxresults="1",
language="es-ES", # this will build the query string
header="true",
indelim="|",
outdelim="|",
outcols="displayLatitude,displayLongitude,houseNumber,street,district,city,postalCode,county,state,country,matchLevel,relevance", # i shortened this for the example
outputCombined="false",
app_code="AJKnXv84fjrb0KIHawS0Tg",
app_id="DemoAppId01082013GAL"),
#config=c(add_headers("multipart/form-data;boundary=----------------------------4ebf00fbcf09")),
verbose()) # this lets you verify what's going on
content(a)
The problem I had to get around was that the normal upload process strips line breaks... but I needed them in there for the API to work (--data-binary option in curl does this). To get around this, I insert the data as a string after reading it via readLines().
I am trying to get data from the mobile analytics service Localytics via their API (https://api.localytics.com/docs#query). In particular I would like to translate the following cURL command in R:
curl --get 'https://api.localytics.com/v1/query' \
--user 'API_KEY:API_SECRET' \
--data 'app_id=APP_ID' \
--data 'metrics=users' \
--data 'dimensions=day' \
--data-urlencode 'conditions={"day":["between","2013-04-01","2013-04-07"]}'
My R code looks like this at the moment. APIKey and API secret are of course replaced by the actual keys. However, I receive an error stating that at least a dimension or a metric has to be specified.
object <- getURL('https://api.localytics.com/v1/query', userpwd = "API_Key:API_Secret", httpheader=list(app_id = "app_id=03343434353534",
metrics = "metrics=users",
dimensions = "dimensions=day",
conditions = toJSON('conditions={"day":["between","2014-07-01","2014-07-10"]}')), ssl.verifypeer = FALSE)
What changes would be necessary to get it to work.
Thanks in advance for helping me out,
Peter
This is particular easy with the dev version of httr:
library(httr)
r <- POST('https://api.localytics.com/v1/query',
body = list(
app_id = "APP_ID",
metrics = "users",
dimensions = "day",
conditions = list(
day = c("between", "2014-07-01", "2004-07-10")
)
),
encode = "json",
authenticate("API_key", "API_secret")
)
stop_for_status(r)
content(r)
(I converted the request to a POST and used json encoding for everything, as describe in the API docs).
If you want to see exactly what's being sent to the server, use the verbose() config.
It looks like getURL passes the parameters you quested as HTTP headers and not as querystring data as your curl call does. You should use getForm instead. Also, I wasn't sure from which library your toJSON function came form, but that's at least not the right syntax for the one from rsjon.
Anyway, here's a call from R which should produce the same HTTP call are your curl command
library(rjson)
library(RCurl)
object <- getForm('https://api.localytics.com/v1/query',
app_id = "APP_ID",
metrics = "users",
dimensions = "day",
conditions = toJSON(list(day=c("between","2014-07-01","2004-07-10"))),
.opts=curlOptions(
userpwd = "API_Key:API_Secret", httpauth = 1L)
)
I found that using the site http://requestb.in/ is very helpful in debugging these problems (and that's exactly what I used to create this solution). You can send requests to their site and they record the exact HTTP message that was sent so you can compare different methods.
The httpauth part was from this SO question which seemed to be required to trigger authentication for the test site; you may not need it for the "real" site.
I am trying to create an OAuth token from the command line using the instructions here. I am able to use curl from the command line, and get the correct response
curl -u 'username:pwd' -d '{"scopes":["user", "gist"]}' \
https://api.github.com/authorizations
Now, I want to replicate the same in R using RCurl or httr. Here is what I tried, but both commands return an error. Can anyone point out what I am doing wrong here?
httr::POST(
'https://api.github.com/authorizations',
authenticate('username', 'pwd'),
body = list(scopes = list("user", "gist"))
)
RCurl::postForm(
uri = 'https://api.github.com/authorizations',
.opts = list(
postFields = '{"scopes": ["user", "gist"]}',
userpwd = 'username:pwd'
)
)
The question is ages old, but maybe still helpfull to some: The problem should be that the opts arguments are passed in the wrong way (lacking a curlOptions function call). The following worked for me in a different context:
result <- getURL(url,.opts=curlOptions(postfields=postFields))
(and yes, as far as I know you can use getURL function for POST requests).