I thought this would address my use case, but I've run into some snags. First to answer your questions:
For my purposes, the val() variable doesn't have to be shared across sessions, and if it did, my understanding is that I could use a '<<-' operator to assign the variable inside the server function, and that variable would then alter the variable across multiple sessions. I haven't tested that, but as I said, it's not necessary for the problem I am seeking to address.
I have unfortunately hit a snag that my solution does not address, so let me take a step back and explain my precise use case. When a user attempts to access one of our shiny apps, their URL will be assigned a session token that can be accessed by the app. The first thing any of my shiny apps needs to do is query our database for all valid session tokens. If the session token is seen to be valid, I want the ui to paint normally otherwise I want to generate a 401 page (ideally a real 401, but I really am out of my depth here).
The solution that I checked above does achieve this from the stand point that it can grab the session token object, query the database from within the server function (which means that it will always have a list of valid tokens as of the moment that the app was accessed), and then pass the true/false logic to a renderUI to paint the entire ui for the app if it works, or paint a basic HTML 401 error if the check fails.
The problem is that I have some fairly complex shiny apps that I have to integrate this functionality to and defining the entire ui from within the server function is tricky, and has introduced some fairly inconsistent behavior.
Initially I was attempting to move the logic to the app space so that a basic ui function (ui_func in my example) could take the place of the ui in the shinyApp call. This would reduce the overhead of having to totally reinvent all of my uis and move them to the server. This ran into the problem that I originally had where I couldn't get a fresh copy of the valid session tokens from a database call in the app scope (the stale copy of the valid session tokens was keeping any subsequent session calls from getting an updated version).
This is exemplary of my current (and not at all ideal) framework:
# Easter Egg is displayed if /?query=123; 401 displayed if /?query=anything else
library(shiny)
ui <- uiOutput("ui")
server <- function(input, output, session) {
# Valid Query Object defined in each session (this would be a database call)
validQuery <- "123"
# Parsing the session token from the URL
# This is defined before the app launches in my actual use case
query <- reactive({parseQueryString(session$clientData$url_search)})
# TRUE/FALSE that the two values match
output$queryMatch <- renderText({
req(query())
paste(query() == validQuery)
})
# Parse the GET query string
output$queryText <- renderText({
paste(names(query()), query(), sep = "=", collapse=", ")
})
# If there is a query in the URL and it matches the validQuery, render a selectInput
# This is a placeholder for all of the various renderUI objects I have in my apps
output$easterEgg <- renderUI({
req(length(query()) > 0 && query() == validQuery)
selectInput("easterEgg", "So Long as Queries Match...", choices = c("foo", "bar", validQuery), selected = validQuery)
})
# Send the Complete renderUI to the ui in app scope to be rendered if the query is
# either absent or is present AND == validQuery, otherwise paint a 401
output$ui <- renderUI({
if(length(query()) > 0 && query() != validQuery) {
HTML("<strong>This is a 401 Error<strong>")
} else {
bootstrapPage(
h3("Parsed query string"),
verbatimTextOutput("queryText"),
h3("A valid query would look like '/?query=123'"),
verbatimTextOutput("queryMatch"),
uiOutput("easterEgg")
)
}
})
}
shinyApp(ui, server)
Ideally I could create a shiny module that could be called as far upstream as possible that makes the determination before the server has to be called.
# Need to be able to have an updated valid session list every time the
# app is accessed
validQuery <- dbGetQuery(con, "select valid_token from token_table")
# if there is a way to parse the URL before the server function is called
# that would be great
query <- parseQueryString(session$clientData$url_search)
if(length(query()) > 0 && query() == validQuery) {
bootstrapPage(
h3("Parsed query string"),
verbatimTextOutput("queryText"),
h3("A valid query would look like '/?query=123'"),
verbatimTextOutput("queryMatch"),
uiOutput("easterEgg")
)
} else {
HTML("<strong>This is a 401 Error<strong>")
}