Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R Shiny/ Restful Api Communication

I have a shiny app that takes a JSON input file, runs it through a classifier and returns a classified JSON object. I want the app to be able to communicate with an API. I want the API to post a file to the Shiny App which will do its work and return a classified object. Basically I want the Shiny app to sit in the background until a file is posted and then do its work. I know that I can use GET from the httr package to get a file from a url. I can put this in the shiny.server file which is fine if I know the file name for the get command

However the filenames coming from the API will be different. So is there any way that I can make this dynamic according to the Post request that comes from the API.

like image 658
user2987739 Avatar asked Aug 13 '14 10:08

user2987739


People also ask

Is R Shiny difficult?

Along with Shiny elements, you can use HTML elements to stylize your content in your application. In my opinion, R Shiny is very easy to learn despite how powerful the tool is. If you're working on a side project or looking to add something to your portfolio, I highly recommend trying it out.

How does R Shiny work?

Shiny comes with a reactive programming library that you will use to structure your application logic. By using this library, changing input values will naturally cause the right parts of your R code to be reexecuted, which will in turn cause any changed outputs to be updated.

How do you show a message in Shiny?

Simply call shinyalert() with the desired arguments, such as a title and text, and a modal will show up. In order to be able to call shinyalert() in a Shiny app, you must first call useShinyalert() anywhere in the app's UI.

What is an R Rest API?

REST APIs are everywhere around us. Software engineers use them to develop backend logic, and data scientists use them to deploy machine learning models. Today you’ll learn how to make a basic REST API with R and the plumber package. Completely new to R? Check out our detailed R tutorial for programmers.

How to handle post requests in shiny?

You can handle POST requests in Shiny with the help of the function session$registerDataObj. An example of using this function can be found in this example. Basically, by calling registerDataObj function, it returns a unique request URL to which you can initiate either GET or POST requests.

What is the type and message in shiny?

The type is an identifier string that will help Shiny identify the correct JavaScript code to invoke when the message is received. As usual, it’s best to stick to simple identifiers with alphanumeric characters, undercores, and periods. The message is any R object that can be encoded to JSON.

Does shiny care about the latest value of a reactive input?

By default, Shiny assumes that your app only cares about the latest value of a reactive input. Shiny.setInputValue uses this assumption to perform two optimizations by default:


2 Answers

If you do not have to use Shiny, you can use openCPU. OpenCPU provides each of your R packages as REST service automatically. I work with OpenCPU and it works fine! It is the easiest way to use R from another program.

like image 161
Guybrush Avatar answered Oct 08 '22 09:10

Guybrush


By now library(plumber) needs to be mentioned as an alternative in this context, however the following example is showing how to handle POST requests directly in shiny.

It is based on Joe Cheng's gist here, which suggests to add an attribute "http_methods_supported" to the UI and use httpResponse to answer the requests.

The below code starts a shiny app in a background R process (This is done only to have a single single file MRE - of course, you can put the app in a separate file and remove the r_bg-line). After the app is launched the parent process sends the iris data.frame to the UI.

In the UI function the req$PATH_INFO is checked (see uiPattern = ".*"), then the numerical columns are multiplied by 10 (query_params$factor) and send back as a json string.

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

Please also check this related PR which is providing further examples (also showing how to use session$registerDataObj) and is aiming at a better description of the httpResponse function.

like image 2
ismirsehregal Avatar answered Oct 08 '22 08:10

ismirsehregal