library(curl)
library(promises)
curl_fetch_async <- function(url, pool = NULL, data = NULL, handle = new_handle()) {
p <- promises::promise(function(resolve, reject) {
curl_fetch_multi(url, done = resolve, fail = reject, pool = pool, data = data, handle = handle)
})
finished <- FALSE
poll <- function() {
if (!finished) {
multi_run(timeout = 0, poll = TRUE, pool = pool)
later::later(poll, 0.01)
}
}
poll()
p %>% finally(function() {
finished <<- TRUE
})
}
# A way of sending an HTTP request using a socketConnection. This isn't as
# reliable as using curl, so we'll use it only when curl can't do what we want.
http_request_con_async <- function(request, host, port) {
resolve_fun <- NULL
reject_fun <- NULL
con <- NULL
p <- promises::promise(function(resolve, reject) {
resolve_fun <<- resolve
reject_fun <<- reject
con <<- socketConnection(host, port)
writeLines(c(request, ""), con)
})
result <- NULL
# finished <- FALSE
poll <- function() {
result <<- readLines(con)
if (length(result) > 0) {
resolve_fun(result)
} else {
later::later(poll, 0.01)
}
}
poll()
p %>% finally(function() {
close(con)
})
}
wait_for_it <- function() {
while (!later::loop_empty()) {
later::run_now()
}
}
# Block until the promise is resolved/rejected. If resolved, return the value.
# If rejected, throw (yes throw, not return) the error.
extract <- function(promise) {
promise_value <- NULL
error <- NULL
promise %...>%
(function(value) promise_value <<- value) %...!%
(function(reason) error <<- reason)
wait_for_it()
if (!is.null(error))
stop(error)
else
promise_value
}
# Make an HTTP request using curl.
fetch <- function(url, handle = curl::new_handle(), gzip = TRUE) {
if (!gzip) {
# Disable gzip; this is often needed only because the unit tests predate
# gzip support in httpuv
handle_setopt(handle, accept_encoding = NULL)
}
p <- curl_fetch_async(url, handle = handle)
extract(p)
}
# Make an HTTP request using a socketConnection. Not as robust as fetch(), so
# we'll use this only when necessary.
http_request_con <- function(request, host, port) {
p <- http_request_con_async(request, host, port)
extract(p)
}
local_url <- function(path, port) {
stopifnot(grepl("^/", path))
paste0("http://127.0.0.1:", port, path)
}
parse_http_date <- function(x) {
strptime(x, format = "%a, %d %b %Y %H:%M:%S GMT", tz = "GMT")
}
raw_file_content <- function(filename) {
size <- file.info(filename)$size
readBin(filename, "raw", n = size)
}
# Given a POSIXct object, return a date string in the format required for a
# HTTP Date header. For example: "Wed, 21 Oct 2015 07:28:00 GMT"
http_date_string <- function(time) {
weekday_names <- c("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat")
weekday_num <- as.integer(strftime(time, format = "%w", tz = "GMT"))
weekday_name <- weekday_names[weekday_num + 1]
month_names <- c("Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec")
month_num <- as.integer(strftime(time, format = "%m", tz = "GMT"))
month_name <- month_names[month_num]
strftime(time,
paste0(weekday_name, ", %d ", month_name, " %Y %H:%M:%S GMT"),
tz = "GMT"
)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.