2015-08-25 3 views
3

Я пытаюсь выполнить асинхронные запросы к REST API из R. Команда ниже curl показывает параметры, которые мне нужны для прохождения к api. Я даю вам ребята команду Linux локон, как я надеюсь, что станет ясно:Асинхронные запросы POST - R, используя RCURL?

curl -v -X POST https://app.example.com/api/ \ 
-H 'Authorization: somepwd' \ 
-H "Content-Type: application/json" \ 
-d {key1: value1, key2: value2} 

Прямо сейчас, я выполнения то же самое в R, выполнив следующие действия:

library(httr) 
library(jsonlite) 
content(POST('https://app.example.com/api/' 
        ,add_headers(Authorization = 'somepwd') 
        ,body = toJSON(rDataFrame) 
        ,content_type_json() 
      ) 
     ) 

Цель состоит в том, чтобы отправить вышеуказанный запрос POST из R, но изменить строку json, которая отправлена ​​в теле, и сделать это асинхронно.

Я искал пакеты, которые помогут мне делать асинхронные запросы, а не делать запросы поочередно. Самое близкое, что я мог найти, это функция getURIAsynchronous() из пакета RCurl (https://cran.r-project.org/web/packages/RCurl/RCurl.pdf), но не понимаю, как отправить запрос PUT с заголовками и телом, используя их функцию. Я действительно хотел бы сделать вышеуказанный запрос POST от R, но асинхронно, где URI один и тот же, но отправленные данные различны для каждого запроса.

Я нашел это http://www.omegahat.org/RCurl/concurrent.html

getURIs = 
function(uris, ..., multiHandle = getCurlMultiHandle(), .perform = TRUE) 
{ 
    content = list() 
    curls = list() 

    for(i in uris) { 
    curl = getCurlHandle() 
    content[[i]] = basicTextGatherer() 
    opts = curlOptions(URL = i, writefunction = content[[i]]$update, ...)  
    curlSetOpt(.opts = opts, curl = curl) 
    multiHandle = push(multiHandle, curl) 
    } 

    if(.perform) { 
    complete(multiHandle) 
    lapply(content, function(x) x$value()) 
    } else { 
    return(list(multiHandle = multiHandle, content = content)) 
    } 
} 

Моя идея заключается в том, что я мог бы заменить for (i in uris) с for(i in jsons) где я зацикливание по разным данным, которые я хочу, чтобы отправить на тот же URL, но у меня возникли проблемы с пониманием следующие концепции RCURL:

  1. Как передать заголовок как часть запроса PUT. Как передать данные в теле запроса? Это было довольно просто, используя пакет httr, как я уже показал выше.

  2. Я пробовал пропустить в заголовке параметры завивки и, наоборот, заголовок. Дело в том, что я не понимаю, куда передать составные части почтового запроса: аутентификацию, заголовок и тело в пределах функции getURIAsynchronous() или любого из ресурсов, которые я описал выше.

Кто-нибудь знает, как это осуществить? Пример был бы невероятно полезен.

ответ

1

Пакет curl был недавно обновлен для обработки запросов асинхронных (see here)

Использования пакетов curl, magrittr и jsonlite вы можете создавать асинхронные почтовые запросы от:

  • Создания родовой ручки с вашим содержимого заголовка и тела с использованием функции handle_setform
  • Написание функции обратного вызова для извлечения ваших результатов
  • Инициализация пула и добавление ваших одновременных запросов к ней
  • Запуск бассейн через multi_run

Пример кода ниже:

library(curl) 
library(jsonlite) 
library(magrittr) 

#create a handle object 
h <- new_handle() %>% 
handle_setheaders(Authorization = "somepwd", 
        "Content-Type" = "application/json") %>% 
    handle_setform(body = toJSON(iris)) 

pool <- new_pool() 
# results only available through call back function 
cb <- function(req){cat("done:", req$url, ": HTTP:", req$status, "\n", "content:", rawToChar(req$content), "\n")} 

# example vector of uris to loop through 
uris <- c("https://app.example.com/api/endpoint1" 
      ,"https://app.example.com/api/endpoint2" 
      ,"https://app.example.com/api/endpoint3") 

# all scheduled requests are performed concurrently 
sapply(uris, curl_fetch_multi, done=cb, pool=pool) 

# This actually performs requests 
out <- multi_run(pool = pool)