Accept HTTP Request in R shiny application
You can receive GET requests using session$clientData
. An example run the following
library(shiny)
runApp(list(
ui = bootstrapPage(
textOutput('text')
),
server = function(input, output, session) {
output$text <- renderText({
query <- parseQueryString(session$clientData$url_search)
paste(names(query), query, sep = "=", collapse=", ")
})
}
), port = 5678, launch.browser = FALSE)
and navigate to
http://127.0.0.1:5678/?transformerData=data/TransformerDataSampleForShiny.json
See @Xin Yin answer for a method to expose POST requests.
Is there a way to request a Shiny app via GET?
This can be done via plumber (httr
can be used on the client side).
The following creates plumber API which runs a shiny app in a background R process and returns the according port of the shiny app once the port
endpoint is accessed:
library(plumber)
library(shiny)
library(httpuv)
library(callr)
#* @apiTitle Shiny runApp API
#* @apiDescription runs a shiny app and returns the port.
#* Echo back the input
#* @param port The shiny app port
#* @get /port
function() {
ui <- fluidPage(
h1("This is a test app")
)
server <- function(input, output, session) {}
app <- shinyApp(ui, server)
port <- httpuv::randomPort()
r_bg(function(app, port){
shiny::runApp(appDir = app,
port = port,
launch.browser = FALSE,
host = "0.0.0.0")
}, args = list(app = app, port = port), supervise = TRUE)
port
}
# plumb(file='plumber.R')$run()
# http://127.0.0.1:6107/port
Also see my answer here on how to handle http verbs directly with a shiny app.
R shiny - How send a request url with params to R shiny and get just the data response?
I don't believe you can do that using just Shiny. There are, however, some options to have R behave like an API and return JSON responses. See: http://plumber.trestletech.com/
Return HTTP status codes in R Shiny application
I would suggest using shinyjs to start the session with all UI hidden, and then show the UI only if an authorized user makes the connection.
For example, the following app only show UI to logged-in users. I'm substituting the authorization status with radio buttons to simplify the example, but the logic is the same.
# ui.R
fluidPage(
useShinyjs(),
h1("User Authentication Example"),
radioButtons("login", "Login:", c("Logged out", "Logged in")),
div(id = "logged.in.ui",
p("You are logged in")
) %>% shinyjs::hidden()
)
# server.R
library(shinyjs)
function(input, output) {
# Showing/hiding UI depending on login status.
observeEvent(input$login, {
if (input$login == "Logged in") {
shinyjs::show("logged.in.ui")
} else {
shinyjs::hide("logged.in.ui")
}
})
}
Note the %>% shinyjs::hidden
in the UI portion of the above app. This functions to hide all UI within the logged.in.ui div using JavaScript when the session is created and before the login status is checked in the server. Toggling the radio buttons is observed in the server, and the UI content of the logged.in.ui div is shown or hidden depending on the login status.
Shiny Server reacts to browser URL but not GET from httr
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()
Related Topics
Can Dplyr Join on Multiple Columns or Composite Key
How to Maintain Size of Ggplot with Long Labels
Import Data into R with an Unknown Number of Columns
How to Change the Figure Caption Format in Bookdown
How to Make Grouped Layout in Igraph
Convert a Date Vector into Julian Day in R
Merge Panel Data to Get Balanced Panel Data
Ggplot for Loop Outputs All the Same Graph
How to Suppress the Vertical Gridlines in a Ggplot2 Plot
Stepwise Regression Using P-Values to Drop Variables with Nonsignificant P-Values
R Scatter Plot: Symbol Color Represents Number of Overlapping Points
Split/Subset a Data Frame by Factors in One Column
Ggplot Replace Count with Percentage in Geom_Bar
Is There a _Fast_ Way to Run a Rolling Regression Inside Data.Table
How to Export S3 Method So It Is Available in Namespace