From 596165e4731217b96abbce8aba67b30b57eebc21 Mon Sep 17 00:00:00 2001 From: Garrick Aden-Buie Date: Tue, 18 Apr 2023 11:42:34 -0400 Subject: [PATCH 1/3] Set cache control headers to avoid caching UI --- R/shinyui.R | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/R/shinyui.R b/R/shinyui.R index 991f81b479..b7b0ad2650 100644 --- a/R/shinyui.R +++ b/R/shinyui.R @@ -231,11 +231,24 @@ uiHttpHandler <- function(ui, uiPattern = "^/$") { if (is.null(uiValue)) return(NULL) - if (inherits(uiValue, "httpResponse")) { - return(uiValue) - } else { + # Avoid caching the UI response to ensure that UI is always re-evaluated. + # This is necessary for getCurrentTheme() to be known, required for BS4+. + no_cache_headers <- list( + "Cache-Control" = "no-cache, no-store, must-revalidate", + "Pragma" = "no-cache", + "Expires" = "0" + ) + + if (!inherits(uiValue, "httpResponse")) { html <- renderPage(uiValue, showcaseMode, testMode) - return(httpResponse(200, content=html)) + uiValue <- httpResponse(200, content=html) } + + if (!"Cache-Control" %in% names(uiValue$headers)) { + # A custom UI func could set cache-control, otherwise disable UI caching + uiValue$headers <- utils::modifyList(uiValue$headers, no_cache_headers) + } + + uiValue } } From 7909389f0a09e2a1f4cbd9cf43d11d2342e42f92 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Tue, 18 Apr 2023 15:34:15 -0400 Subject: [PATCH 2/3] Only disable cache if a theme has been set --- R/shinyui.R | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/R/shinyui.R b/R/shinyui.R index b7b0ad2650..b9ae5b27c1 100644 --- a/R/shinyui.R +++ b/R/shinyui.R @@ -244,7 +244,12 @@ uiHttpHandler <- function(ui, uiPattern = "^/$") { uiValue <- httpResponse(200, content=html) } - if (!"Cache-Control" %in% names(uiValue$headers)) { + if ( + # A {bslib} theme has been set while generating the UI + !is.null(getCurrentTheme()) && + # The user has not set a `Cache-Control` policy within their UI func + !"Cache-Control" %in% names(uiValue$headers) + ) { # A custom UI func could set cache-control, otherwise disable UI caching uiValue$headers <- utils::modifyList(uiValue$headers, no_cache_headers) } From f8a91fb2e3403f0579c00cf55d83497efc8d3448 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Tue, 18 Apr 2023 21:34:18 -0400 Subject: [PATCH 3/3] Always disable UI cache (unless there's an existing `Cache-Control` header) --- R/shinyui.R | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/R/shinyui.R b/R/shinyui.R index b9ae5b27c1..9127b2e56b 100644 --- a/R/shinyui.R +++ b/R/shinyui.R @@ -244,13 +244,16 @@ uiHttpHandler <- function(ui, uiPattern = "^/$") { uiValue <- httpResponse(200, content=html) } + # 2023-04-23 jcheng5: Example app in PR comment + # https://github.com/rstudio/shiny/pull/3810#issuecomment-1513828996 + # > I think we should always add the cache-busting headers. Without it, + # Connect and ShinyApps.io configurations will have problems in that the + # workerId could be a stale value. if ( - # A {bslib} theme has been set while generating the UI - !is.null(getCurrentTheme()) && - # The user has not set a `Cache-Control` policy within their UI func - !"Cache-Control" %in% names(uiValue$headers) + # The user has not set a `Cache-Control` policy within their UI func + !"Cache-Control" %in% names(uiValue$headers) ) { - # A custom UI func could set cache-control, otherwise disable UI caching + # Disable caching for the UI's response uiValue$headers <- utils::modifyList(uiValue$headers, no_cache_headers) }