Search code examples
rhttpshinygethttr

Shiny Server reacts to browser URL but not GET from httr


I'm trying to write an RShiny application that will accept a URL, read in one file and write to another file based on parameters in the URL. Basing my approach on R Shiny REST API communication this answer.

Below is a minimal functioning code to generate the app - and when I run it from a browser like Chrome (e.g. just entering the address http://127.0.0.1/?outDest=test2), it will create a file. But if I try to call it using a GET call from httr, it generates an error

could not find function "data_read"

Which makes sense, because that function is available to the server and not the ui, is my understanding at least.

So what I want to do, I think, is have the UI read in and parse the GET query - then trigger a reactiveEvent on the server side to take that data, but I can't get that to generate the output I want.

Is there a way for RShiny to handle this? Or another package - should I be looking at plumber?

Many thanks, Aodhán

library(shiny)
library(rjson)
library(callr)
library(httr)


data_read <- function(x) {
    
    json = fromJSON(file = x)
    dat_df <- bind_rows(lapply(json,as.data.frame))
    
}


    
shiny_UI <- function(req) {
  # The `req` object is a Rook environment
  # See https://github.com/jeffreyhorner/Rook#the-environment
  if (identical(req$REQUEST_METHOD, "GET")) {   
    x = data_read("C:/Users/Z0049Y2S/Documents/test.json")
    query_params <- parseQueryString(req$QUERY_STRING)
    #print(query_params)
    if(length(query_params$outDest) ){
        output_Destination = query_params$outDest
        print(output_Destination)
        write.csv("Hello",paste0(output_Destination,".csv"))
    }
    fluidPage(
      h1("Accepting POST requests from Shiny")
    )
  } 
}

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

Solution

  • Shiny apps are really designed to communicate with a client via websockets. For handling HTTP requests, you might want to consider a different approach, e.g. a plumber API.

    Here's a tailored example of that:

    p <- callr::r_bg(
      function() {
        library(plumber)
    
        pr() |>
          pr_handle("GET", "/", function(outFile) {
            write("Hello", outFile)
          }) |>
          pr_run(port = 9850)
      }
    )
    
    httr::GET("http://127.0.0.1:9850?outFile=hello.txt")
    readLines("hello.txt")
    
    p$kill()