R Shiny REST API 通信

34
我有一个Shiny应用程序,它接收JSON输入文件,通过分类器运行,并返回分类的JSON对象。 我希望该应用程序能够与API进行通信。 我想让API将文件发布到Shiny应用程序中,然后执行其工作并返回分类对象。 基本上,我希望Shiny应用程序在后台运行,直到发布文件,然后执行其工作。 我知道可以使用httr包中的GET从url获取文件。如果我知道get命令的文件名,则可以将此命令放在shiny.server文件中,这很好。 但是来自API的文件名将是不同的。 所以,是否有任何方法可以根据来自API的POST请求动态地进行处理呢?

嗨,那正是我想要做的。 - user2987739
4
您可以采取至少两种方式来实现此操作。如果您更喜欢通过AJAX请求来实现,您可以查看这个例子。或者您也可以使用自定义的input绑定output绑定 - Xin Yin
2
我给你的AJAX示例并不是非常直观。例如,它没有演示如何在javascript中构造AJAX请求。相反,它直接将AJAX URL绑定到selectize.js控件上。在这个答案中可以找到一个更明确的在Shiny中使用AJAX请求的示例,尽管还有一些微小的改进空间。 - Xin Yin
嗨Xin,感谢你的帮助。最终我发现将我的Shiny应用程序封装在一个函数中,并通过命令行从我的API运行它更容易。 - user2987739
1
这里只是为了链接到一个相关问题:在 R Shiny 应用程序中接受 HTTP 请求 - blong
显示剩余2条评论
2个回答

11

如果您不必使用Shiny,您可以使用OpenCPU。 OpenCPU会自动将您的每个R包提供为REST服务。我使用OpenCPU,并且它运行良好!这是从另一个程序中使用R的最简单方法。


5
到目前为止,在这种情况下需要提到library(plumber)作为替代方案,但以下示例展示了如何直接在shiny中处理POST请求。
它基于Joe Cheng的gist here,建议在UI中添加属性“http_methods_supported”,并使用httpResponse来回答请求。
以下代码在后台R进程中启动一个闪亮的应用程序(这仅是为了拥有单个文件MRE - 当然,您可以将应用程序放在单独的文件中并删除r_bg行)。启动应用程序后,父进程将iris数据框发送到UI。
在UI函数中,检查req$PATH_INFO(请参见uiPattern = ".*"),然后将数字列乘以10(query_params$factor)并作为json字符串发送回来。
library(shiny)
library(jsonlite)
library(callr)
library(datasets)

ui <- function(req) {
  # The `req` object is a Rook environment
  # See https://github.com/jeffreyhorner/Rook#the-environment
  if (identical(req$REQUEST_METHOD, "GET")) {
    fluidPage(
      h1("Accepting POST requests from Shiny")
    )
  } else if (identical(req$REQUEST_METHOD, "POST")) {
    # Handle the POST
    query_params <- parseQueryString(req$QUERY_STRING)
    body_bytes <- req$rook.input$read(-1)
    if(req$PATH_INFO == "/iris"){
      postedIris <- jsonlite::fromJSON(rawToChar(body_bytes))
      modifiedIris <- postedIris[sapply(iris, class) == "numeric"]*as.numeric(query_params$factor)
      httpResponse(
        status = 200L,
        content_type = "application/json",
        content = jsonlite::toJSON(modifiedIris, dataframe = "columns")
      )
    } else {
      httpResponse(
        status = 200L,
        content_type = "application/json",
        content = '{"status": "ok"}'
      )
    }
  }
}
attr(ui, "http_methods_supported") <- c("GET", "POST")

server <- function(input, output, session) {}

app <- shinyApp(ui, server, uiPattern = ".*")
# shiny::runApp(app, port = 80, launch.browser = FALSE, host = "0.0.0.0")
shiny_process <- r_bg(function(x){ shiny::runApp(x, port = 80, launch.browser = FALSE, host = "0.0.0.0") }, args = list(x = app))

library(httr)
r <- POST(url = "http://127.0.0.1/iris?factor=10", body = iris, encode = "json", verbose())
recievedIris <- as.data.frame(fromJSON(rawToChar(r$content)))
print(recievedIris)
shiny_process$kill()

请查看 相关PR,其中提供了更多示例(还展示了如何使用session$registerDataObj),并旨在更好地描述httpResponse函数。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接