2015-08-25 61 views
3

我试图从R向REST API发出异步请求。下面的curl命令说明了我需要传递给api的参数。我给你们了Linux curl命令,因为我希望将明确:异步POST请求 - R,使用RCurl?

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

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

现在,我通过执行以下完成同样的事情中的R

目标是提交来自R的上述POST请求,但改变在正文中发送的json字符串,并且异步执行

我一直在寻找能够帮助我制作异步请求而不是串行发出请求的软件包。我能找到的最接近的东西是来自RCurl包(https://cran.r-project.org/web/packages/RCurl/RCurl.pdf)的getURIAsynchronous()函数,但不知道如何使用它们的函数提交包含头和实体的PUT请求。我真的很想从R做出上述POST请求,但是在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. 我试着在curl选项中传递头文件,或者在头文件中传递。问题是我不明白在哪里传递post请求的组成部分:getURIAsynchronous()函数中的身份验证,头文件和主体,或者我上面描述的任何资源。

有谁知道如何做到这一点?一个例子会非常有帮助。

回答

1

curl包最近已经更新来处理异步请求(see here

使用curlmagrittrjsonlite包,您可以创建异步POST请求:

  • 创建一个通用的处理您的标题和正文内容使用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)