Skip to content

Commit 1b8d822

Browse files
committed
Fix rstudio#2385: R Markdown documents containing subapps not rendering properly
1 parent f5392d7 commit 1b8d822

File tree

2 files changed

+41
-8
lines changed

2 files changed

+41
-8
lines changed

NEWS.md

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
1-
shiny 1.3.1
1+
shiny 1.3.2
22
===========
33

4-
## Full changelog
4+
### Bug fixes
55

6-
### Breaking changes
6+
* Static CSS/JS resources in subapps in R Markdown documents did not render properly. ([#2386](https://github.com/rstudio/shiny/pull/2386))
77

8-
### New features
98

10-
### Minor new features and improvements
9+
shiny 1.3.1
10+
===========
1111

1212
### Bug fixes
1313

1414
* Fixed a performance issue introduced in v1.3.0 when using large nested lists within Shiny. ([#2377](https://github.com/rstudio/shiny/pull/2377))
1515

16-
### Documentation Updates
17-
1816

1917
shiny 1.3.0
2018
===========

R/server.R

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ registerClient <- function(client) {
2323

2424

2525
.globals$resourcePaths <- list()
26+
.globals$resources <- list()
2627

2728
.globals$showcaseDefault <- 0
2829

@@ -69,8 +70,41 @@ addResourcePath <- function(prefix, directoryPath) {
6970
getShinyOption("server")$setStaticPath(.list = stats::setNames(normalizedPath, prefix))
7071
}
7172

72-
# .globals$resourcePaths persists across runs of applications.
73+
# .globals$resourcePaths and .globals$resources persist across runs of applications.
7374
.globals$resourcePaths[[prefix]] <- staticPath(normalizedPath)
75+
# This is necessary because resourcePaths is only for serving assets out of C++;
76+
# to support subapps, we also need assets to be served out of R, because those
77+
# URLs are rewritten by R code (i.e. routeHandler) before they can be matched to
78+
# a resource path.
79+
.globals$resources[[prefix]] <- list(
80+
directoryPath = normalizedPath,
81+
func = staticHandler(normalizedPath)
82+
)
83+
}
84+
85+
resourcePathHandler <- function(req) {
86+
if (!identical(req$REQUEST_METHOD, 'GET'))
87+
return(NULL)
88+
89+
path <- req$PATH_INFO
90+
91+
match <- regexpr('^/([^/]+)/', path, perl=TRUE)
92+
if (match == -1)
93+
return(NULL)
94+
len <- attr(match, 'capture.length')
95+
prefix <- substr(path, 2, 2 + len - 1)
96+
97+
resInfo <- .globals$resources[[prefix]]
98+
if (is.null(resInfo))
99+
return(NULL)
100+
101+
suffix <- substr(path, 2 + len, nchar(path))
102+
103+
subreq <- as.environment(as.list(req, all.names=TRUE))
104+
subreq$PATH_INFO <- suffix
105+
subreq$SCRIPT_NAME <- paste(subreq$SCRIPT_NAME, substr(path, 1, 2 + len), sep='')
106+
107+
return(resInfo$func(subreq))
74108
}
75109

76110
#' Define Server Functionality
@@ -167,6 +201,7 @@ createAppHandlers <- function(httpHandlers, serverFuncSource) {
167201
http = joinHandlers(c(
168202
sessionHandler,
169203
httpHandlers,
204+
resourcePathHandler,
170205
reactLogHandler
171206
)),
172207
ws = function(ws) {

0 commit comments

Comments
 (0)