Skip to content

Commit

Permalink
Replace RCurl with curl.
Browse files Browse the repository at this point in the history
Closes #172. In passing also switched to using R provided cert bundle. Fixes #223.

cc @jeroenooms
  • Loading branch information
hadley committed May 12, 2015
1 parent 02276fb commit 6e4fdf9
Show file tree
Hide file tree
Showing 53 changed files with 555 additions and 782 deletions.
3 changes: 1 addition & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ Depends:
Imports:
digest,
jsonlite,
methods,
mime,
RCurl (>= 1.95-0),
curl (>= 0.5.9001),
R6,
stringr (>= 0.6.1)
Suggests:
Expand Down
25 changes: 4 additions & 21 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,22 @@
S3method("$",insensitive)
S3method("[",insensitive)
S3method("[[",insensitive)
S3method(as.character,form_file)
S3method(as.character,response)
S3method(c,config)
S3method(c,request)
S3method(cookies,handle)
S3method(cookies,response)
S3method(headers,response)
S3method(length,path)
S3method(print,cache_info)
S3method(print,config)
S3method(print,handle)
S3method(print,oauth_app)
S3method(print,oauth_endpoint)
S3method(print,opts_list)
S3method(print,request)
S3method(print,response)
S3method(print,write_disk)
S3method(print,write_memory)
S3method(print,write_stream)
S3method(status_code,numeric)
S3method(status_code,response)
S3method(write_init,write_disk)
S3method(write_init,write_memory)
S3method(write_init,write_stream)
S3method(write_opts,write_disk)
S3method(write_opts,write_memory)
S3method(write_opts,write_stream)
S3method(write_term,write_disk)
S3method(write_term,write_memory)
S3method(write_term,write_stream)
export(BROWSE)
export(DELETE)
export(GET)
Expand All @@ -47,7 +36,6 @@ export(accept_json)
export(accept_xml)
export(add_headers)
export(authenticate)
export(brew_dr)
export(build_url)
export(cache_info)
export(config)
Expand All @@ -67,6 +55,7 @@ export(hmac_sha1)
export(http_condition)
export(http_date)
export(http_status)
export(httr_dr)
export(httr_options)
export(init_oauth1.0)
export(init_oauth2.0)
Expand Down Expand Up @@ -111,13 +100,7 @@ export(with_config)
export(with_verbose)
export(write_disk)
export(write_function)
export(write_init)
export(write_memory)
export(write_opts)
export(write_stream)
export(write_term)
import(stringr)
importFrom(R6,R6Class)
useDynLib(httr,close_file)
useDynLib(httr,write_callback)
useDynLib(httr,writer)
20 changes: 19 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,24 @@
# httr 0.6.1.9000

* `config()` and `c.config()` now clean up duplicated options (#213).
* The biggest change in this version is that httr no longer uses the RCurl
package. Instead it uses the curl package, fresh binding to libcurl
written by Jeroen Ooms (#172). This should make httr more reliable and
no longer prone to the "easy handle already used in multi handle" error.
This change shouldn't affect any code that uses httr - all the changes
have happened behind the scenes.

* `cookies` argument to `handle()` is deprecated - cookies are always
turned on by default.

* `brew_dr()` has been renamed to `httr_dr()` - that's what it should've
been in the first place!

* Uses `CURL_CA_BUNDLE` environment variable to look for cert bundle on
Windows (#223).

* `safe_callback()` is deprecated - it's no longer needed with curl.

* `config()` now clean up duplicated options (#213).

* `POST()` and `PUT()` now clean up after themselves when uploading a single
file (@mtmorgan).
Expand Down
84 changes: 35 additions & 49 deletions R/body.R
Original file line number Diff line number Diff line change
@@ -1,32 +1,34 @@
body_config <- function(body = NULL, encode = "form", type = NULL) {
# Post without body
if (is.null(body)) return(body_raw(raw()))
if (is.null(body))
return(body_raw(raw()))

# No body
if (identical(body, FALSE)) return(body_httr(post = TRUE, nobody = TRUE))
if (identical(body, FALSE))
return(config(post = TRUE, nobody = TRUE))

# For character/raw, send raw bytes
if (is.character(body) || is.raw(body)) {
return(body_raw(body, type = type))
}

# Send single file lazily
if (inherits(body, "FileUploadInfo")) {
con <- file(body$filename, "rb")
mime_type <- body$contentType %||%
mime::guess_type(body$filename, empty = NULL)
size <- file.info(body$filename)$size
if (inherits(body, "form_file")) {
con <- file(body$path, "rb")
size <- file.info(body$path)$size

return(body_httr(
post = TRUE,
readfunction = function(nbytes, ...) {
bin <- readBin(con, "raw", nbytes)
if (!length(bin))
close(con)
bin
},
postfieldsize = size,
type = mime_type
return(c(
config(
post = TRUE,
readfunction = function(nbytes, ...) {
bin <- readBin(con, "raw", nbytes)
if (!length(bin))
close(con)
bin
},
postfieldsize = size
),
content_type(body$type)
))
}

Expand All @@ -41,50 +43,34 @@ body_config <- function(body = NULL, encode = "form", type = NULL) {
} else if (encode == "json") {
body_raw(jsonlite::toJSON(body, auto_unbox = TRUE), "application/json")
} else if (encode == "multipart") {
# For multipart, rely on RCurl .postForm function to make it possible
# to intermingle on-disk and in-memory content.

charify <- function(x) {
if (inherits(x, "FileUploadInfo")) return(x)
as.character(x)
}
body <- lapply(body, charify)
body <- lapply(body, as.character)
stopifnot(length(names(body)) > 0)

body_rcurl(body = body, style = NA)
request(fields = body)
} else {
stop("Unknown encoding", call. = FALSE)
}
}


body_rcurl <- function(body = NULL, style = NULL) {
list(
config = NULL,
body = body,
style = style,
curl_post = TRUE
)
}

body_httr <- function(..., type = NULL) {
list(
config = c(config(...), content_type(type)),
curl_post = FALSE
)
}

body_raw <- function(body, type = NULL) {
if (!is.raw(body)) {
body <- charToRaw(paste(body, collapse = "\n"))
}

base <- body_httr(
post = TRUE,
postfieldsize = length(body),
postfields = body,
type = type %||% "" # For raw bodies, override default POST content-type
c(
config(
post = TRUE,
postfieldsize = length(body),
postfields = body
),
# For raw bodies, override default POST content-type
content_type(type %||% "")
)
}

base
body_httr <- function(..., type = NULL) {
request()
list(
config = c(config(...), content_type(type))
)
}
15 changes: 7 additions & 8 deletions R/cache.R
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ parse_cache_control <- function(x) {
rerequest <- function(r) {
x <- cache_info(r)
if (!x$cacheable) {
return(reperform(r$request))
return(reperform(r))
}

# Cacheable, and hasn't expired
Expand All @@ -123,14 +123,13 @@ rerequest <- function(r) {
}

# Requires validation
r$request$opts <- c(
r$request$opts,
add_headers(
req <- c(r$request,
request(headers = c(
`If-Modified-Since` = http_date(x$modified),
`If-None-Match` = x$etag
)
))
)
validated <- reperform(r$request)
validated <- request_perform(req, r$handle)

if (status_code(validated) == 304L) {
r
Expand All @@ -139,6 +138,6 @@ rerequest <- function(r) {
}
}

reperform <- function(x) {
perform(x$handle, x$writer, x$method, x$opts, x$body)
reperform <- function(resp) {
request_perform(resp$request, resp$handle)
}
Loading

0 comments on commit 6e4fdf9

Please sign in to comment.