Hi,
I tried to convert our plumber APIs so that they were built up programmatically. I ran into some problems, which as far as I can see, where due to a lack of documentation (or due to me not finding what I was looking for).
It seems that it is not very clear from the documentation that in plumber router handlers only expressions and not functions are executed within the environment defined in the plumber router.
However, I have to call a function of a different namespace (another package) with a very large pre-loaded object. With a bit of research in the unit tests folder of the plumber package and by reading some of the tickets in github, I created the following code in order to resolve this problem (this is a reprex so it looks a bit different but the idea should be the same):
library(namespace)
library(plumber)
library(testthat)
new_env <- new.env()
new_env$data <- datasets::iris
ns <- namespace::makeNamespace("my_namespace")
ns$my_function <- function(req, res, data) {
data
}
namespaceExport(ns, ls(ns))
#> <environment: 0x000000000c649d90>
pr <- plumber::pr(envir = new_env)
pr <- plumber::pr_post(pr,
path = "/path",
handler = local({
function(req, res, ...) {
my_namespace::my_function(req = req,
res = res,
data = data)
}
},
envir = pr$environment))
end <- pr$endpoints[[1]][[1]]
res <- plumber:::PlumberResponse$new()
req <- list()
testthat::expect_equal(end$exec(req = req, res = res), datasets::iris)
My question now is whether this is the best way to get around the problem or whether I have overlooked something and there are better / easier solutions for this.