Description
Background
I'm trying to serve a website via some static JS, HTML and CSS files in RStudio Workbench using a plumber API I'm developing.
The plumber API endpoint serving the static files (as per the docs) is defined as:
#* static files
#* @assets ./dist /
list()
The ./dist
folder containing the static website files is structured like so (with index.html
using relative paths to source all of the various files):
dist
├── assets
│ ├── index-BuF2VGXq.js
│ ├── index-CAJq-P8_.css
│ ├── index-ChuXfzd8.js
│ └── testPage-MBawWazC.js
├── favicon.ico
├── index.html
├── logo192.png
├── logo512.png
├── manifest.json
└── robots.txt
When I run the plumber API, all my other endpoints work as expected, however when I go to the root /
I see the following errors in the browser console:
Failed to load resource: the server responded with a status of 404 (Not Found) index-ChuXfzd8.js:1
Failed to load resource: the server responded with a status of 404 (Not Found) manifest.json:1
This is because the URL in RStudio Workbench is dynamic and uses a proxy in order for it to be accessible via the browser.
For example, when running my API on port 8900 in my Workbench session, http://127.0.0.1:8900
proxies over to https://<workbench_instance>.net/s/a441fcfc78a310d8af850/p/a5d3c674/
.
I can therefore successfully access the static files manually at their relevant endpoints using the full dynamic proxy URL:
https://<workbench_instance>.net/s/a441fcfc78a310d8af850/p/a5d3c674/assets/index-ChuXfzd8.js:1
TL/DR
So in short, my API running in Workbench is (unsuccessfully) trying to access the static files using the base URL:
e.g.
https://<workbench_instance>.net/assets/index-ChuXfzd8.js
which ultimately fails because it's actually served at the full dynamic / proxy URL:
e.g.
https://<workbench_instance>.net/s/a441fcfc78a310d8af850/p/a5d3c674/assets/index-ChuXfzd8.js
My current (hacky) workarounds
1. Hardcode the full dynamic paths into my ./dist/index.html
file
This works but is less than ideal as these are hardcoded and will break when I rebuild the static files, change the port my API is running at, or start a new Workbench session.
2. Dynamically modify the endpoint using rstudioapi::translateLocalUrl
In this workaround I
- Get the translated Workbench proxy URL using
rstudioapi::translateLocalUrl()
for the specific port my API is running at - Use the dynamic
/s/<service ID>/p/<random ID>
portion of the proxy URL defining the current service running the API as a prefix to my plumber API root endpoint
library(plumber)
library(rstudioapi)
port <- 8900
generate_base_path <- function(port = 8900) {
local_url <- glue::glue("http://127.0.0.1:{port}/")
translated_url <- rstudioapi::translateLocalUrl(local_url, absolute = TRUE)
base_path <- sub("http[s]?://[^/]+", "", translated_url)
return(base_path)
}
base_path <- generate_base_path(port = port)
static_router <- PlumberStatic$new("./dist")
pr <- plumber::plumb("./plumber.R")
## Mount the static file folder dynamically to the correct proxy path
pr$mount(paste0(base_path, "/dist"), static_router)
local_url <- glue::glue("http://127.0.0.1:{port}/")
message(glue::glue("Running at: {rstudioapi::translateLocalUrl(local_url, absolute = TRUE)}"))
pr$run(port = port, docs = FALSE)
This is obviously quite convoluted and I was wondering (hoping) if there were any better solutions!
I saw that #60 requests something quite similar, however, unfortunately I cannot in my case use docker / nginx or any other external routing solutions as the admin maintaining the server in which the RStudio Workbench instance is running cannot/won't install docker.