【问题标题】:Asynchronous POST Requests - R, using RCurl?异步 POST 请求 - R,使用 RCurl?
【发布时间】:2015-08-25 03:01:01
【问题描述】:

我正在尝试从 R 向 REST API 发出异步请求。下面的 curl 命令说明了我需要传递给 api 的参数。我给你们 linux curl 命令,因为我希望它会说清楚:

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()
             )
        )

目标是从 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() 函数中的身份验证、标头和正文,或者我上面描述的任何资源。

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

【问题讨论】:

    标签: r asynchronous rcurl httr


    【解决方案1】:

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

    使用curlmagrittrjsonlite 包,您可以通过以下方式创建异步发布请求:

    • 使用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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-21
      • 2021-08-23
      相关资源
      最近更新 更多