9

How I would write the following curl POST method using R and the RCurl package?

curl -k -u myusername:mypassword -d '{"text":"Hello World!","level":"Noob"}' -H "Content-Type: application/json" -H "Accept: application/json" "http://api.website/v1/access?"
GSee
  • 48,880
  • 13
  • 125
  • 145
Jen Daleston
  • 101
  • 1
  • 1
  • 3

2 Answers2

14

FINAL EDIT: After emailing the great Duncan Temple Lang I have a solution:

library(RCurl)
library(RJSONIO)
postForm("http://api.website/v1/access?",
         .opts = list(postfields = toJSON(list(text = "Hello World!", level = "Noob")),
                      httpheader = c('Content-Type' = 'application/json', Accept = 'application/json'),
                      userpwd = "Username:Password",
                      ssl.verifypeer = FALSE))

My previous post is below but it has all now been superseded by the edit above (I've left the below for reference):

I would like to know the answer to this question myself. even looking at TARehman's answer I still can't work out how to do it (my lack of understanding is no doubt the root).

If you download curl from its website (I used the generic-win binary version), then here's one way of doing it in R via the 'system' command which is like using the window's command line window but from R:

output <- system('C:/+/curl-7.27.0-rtmp-ssh2-ssl-sspi-zlib-idn-static-bin-w32/curl  -k -u "username:password" -d "{\\"text\\":\\"Hello World!\\",\\"level\\":\\"Noob\\"}" -H "Content-Type: application/json" -H "Accept: application/json" "http://api.website/v1/access?"', intern = TRUE))

The above works with one of the API's I use. You can then use

I really hope you find an answer because it would be useful for me to know too.

EDIT: My attempt using an actual API with RCurl via @TARehman's example:

Here is the curl code which works fine:

x = system('C:/+/curl-7.27.0-rtmp-ssh2-ssl-sspi-zlib-idn-static-bin-w32/curl  -k -u "USERNAME:PASSWORD" -d "{\\"text\\":\\"Have a nice day!\\"}" -H "Content-Type: application/json" -H "Accept: application/json" "http://api.theysay.io:60000/v1/sentiment?"', intern = TRUE)

And here is how I've rewritten it in RCurl:

curl.opts <- list(userpwd = "username:password", 
                  httpheader = "Content-Type: application/json",
                  httpheader = "Accept: application/json",
                  timeout = 20, 
                  connecttimeout = 20, 
                  verbose = TRUE, 
                  useragent = "RCurl",
                  cainfo = system.file("CurlSSL", "cacert.pem", package = "RCurl"))

postForm("http://api.theysay.io:60000/v1/sentiment?", .params = c(data = '{\\"text\\":\\"Have a nice day!\\"}'), .opts = curl.opts)

This however did not work and results in the following (clearly I have not understood something correctly):

* About to connect() to api.theysay.io port 60000 (#0)
*   Trying 163.1.94.100... * connected
* Connected to api.theysay.io (163.1.94.100) port 60000 (#0)
> POST /v1/sentiment? HTTP/1.1
User-Agent: RCurl
Host: api.theysay.io:60000
Accept: application/json
Content-Length: 193
Expect: 100-continue
Content-Type: multipart/form-data; boundary=----------------------------7620b19c7a5d

< HTTP/1.1 100 Continue
< HTTP/1.1 401 Unauthorized
< WWW-Authenticate: Basic realm="Secured Resource"
< Content-Type: text/plain
< Server: spray-can/1.0-M2.1
< Date: Wed, 12 Sep 2012 12:26:06 GMT
< Content-Length: 77
< 
* Ignoring the response-body
* Connection #0 to host api.theysay.io left intact
* Issue another request to this URL: 'http://api.theysay.io:60000/v1/sentiment?'
* Re-using existing connection! (#0) with host api.theysay.io
* Connected to api.theysay.io (163.1.94.100) port 60000 (#0)
* Server auth using Basic with user '[USERNAME]'
> POST /v1/sentiment? HTTP/1.1
Authorization: Basic [KEY]==
User-Agent: RCurl
Host: api.theysay.io:60000
Accept: application/json
Content-Length: 193
Expect: 100-continue
Content-Type: multipart/form-data; boundary=----------------------------949d191bdaeb

< HTTP/1.1 100 Continue
< HTTP/1.1 415 Unsupported Media Type
< Content-Type: text/plain
< Server: spray-can/1.0-M2.1
< Date: Wed, 12 Sep 2012 12:26:06 GMT
< Content-Length: 93
< 
* Connection #0 to host api.theysay.io left intact
[1] "There was a problem with the requests Content-Type:\nExpected 'text/xml' or 'application/json'"
attr(,"Content-Type")

"text/plain" 
Tony Breyal
  • 5,338
  • 3
  • 29
  • 49
  • I'm not sure how I can make it more clear, but I'd like to help if I can. What seems to be your issue? Or is it better to open your own question? – TARehman Sep 10 '12 at 20:42
  • @TARehman Speaking for myself alone and not the OP, I can get the curl code to work without issue. However, using your example and the docs, I don't think I have correctly rewritten the code into RCurl parlance. See edit. – Tony Breyal Sep 12 '12 at 12:32
  • Hmm. I think you might be better off if you started your own question - but off the top of my head, I would suggest that perhaps you could try passing parameters through postForm, and not through .params. – TARehman Sep 12 '12 at 15:38
  • The postfields part was the most useful to me - for uploading a file with no named parameter. – daveb Oct 10 '12 at 14:02
  • 1
    I realize this is a bit old, but thanks for this. Very helpful! – Ricardo Saporta May 07 '13 at 19:08
  • What is the advantage of doing this in RCurl over putting a simple curl operation in system()? Both just assign the output to a character. – KLDavenport Sep 06 '13 at 01:01
  • @KLDavenport I find it easier to keep track of my code if I don't have system calls all over the place. Plus having an R function usually simplifies the process and might handle things behind the scenes which I haven't thought about. – Tony Breyal Sep 06 '13 at 08:40
  • A big bow to you! Solved my problem. By the way, I'm trying to use this for authentication. How can I get the cookie for that in R? – curlyreggie Feb 05 '14 at 09:51
  • It's a really bad idea to use `ssl.verifypeer = FALSE` – hadley Jul 23 '14 at 21:16
  • @hadley Fair play. I use the httr package now for this kind of stuff as it seems to simplify everything. – Tony Breyal Jul 24 '14 at 10:25
3

In RCurl, there's a function called postForm(), which is what you'd want to use. My generic example:

library(RCurl)

param1 <- "json"
param2 <- "all"
param3 <- "j3kn1kn41" # Hypothetical API token

webobj <- postForm("http://www.thewebsite.com/api/",type=param1,records=param2,token=param3)

Basically, you just pass any parameters you need as named arguments to postForm(), along with the base URL, and it constructs it and posts it, and puts the response into whatever object you declare (webobj) in this case.

If you need to set any curl options, you can use .opts=curlOptions(OPTIONS HERE) to change them.

TARehman
  • 6,659
  • 3
  • 33
  • 60