A. Thibault
A. Thibault

Reputation: 21

R plumber API - mounted router does not shows

I am trying to build a API with Plumber (v0.4.6). I want to use several .R files (one for each function/endpoints of the API) to avoid making one huge .R file with all functions. It work fine with only one .R file using :

pr <- plumb("api/v1/plumber.R")
pr$run()

But when I try to split the plumber file into two separate files, the mounted endpoints does not shows :

root <- plumber$new("api/v1/plumber.R")
test <- plumber$new("api/v1/fct1.R")

root$mount("/test", test)
root$run()

It is weird because root$mounts shows all the endpoints and the API shows only the root's ones (plot and sum) :

# Plumber router with 2 endpoints, 5 filters, and 1 sub-router.
# Call run() on this object to start the API.
├──[queryString]
├──[postBody]
├──[cookieParser]
├──[sharedSecret]
├──[logger]
├──/plot (GET)
├──/sum (POST)
├──/test
│  │ # Plumber router with 1 endpoint, 4 filters, and 0 sub-routers.
│  ├──[queryString]
│  ├──[postBody]
│  ├──[cookieParser]
│  ├──[sharedSecret]
│  └──/test8 (GET)

Here is the code of the two files :

library(plumber)

#* @apiTitle Plumber Example API

#* Plot a histogram
#* @png
#* @get /plot
function() {
    rand <- rnorm(100)
    hist(rand)
}

#* Return the sum of two numbers
#* @param a The first number to add
#* @param b The second number to add
#* @post /sum
function(a, b) {
    as.numeric(a) + as.numeric(b)
}
#* Echo back the input
#* @param msg The message to echo
#* @get /test8
function(msg = "") {
  list(msg = paste0("The message is: '", msg, "'"))
}

Thanks for your help.

Upvotes: 1

Views: 423

Answers (2)

Michal Skop
Michal Skop

Reputation: 1399

The solution/explanation is here: https://community.rstudio.com/t/functions-within-a-sourced-file-are-not-accessible-as-plumber-api-endpoints/64266 or here: https://github.com/rstudio/plumber/issues/533

One way how to achieve it:

It is also possible to create a new file (e.g. api.R) and put all the endpoints there( + name the functions in the sourced files). Doing so we also separate the functions from the API, e.g.:

api.R (a new file):

# plumber.R

source("./main.R")

#* Echo back the input
#* @param msg The message to echo
#* @get /echo
function(msg) {
  main.echo(msg)
}

#* Return "hello world"
#* @get /hello
function(){
  functions.hello()
}

main.R (similar to plumber.R in OP's question):

source("./functions.R")


main.echo = function(msg=""){
  list(msg = paste0("The message is: '", msg, "'"))
}

functions.R (similar to fct1.R in OP's question):

functions.hello = function(){
  "hello world"
}

And then

library(plumber)
pr = plumb("api.R")
pr$run()

And then both /echo and /hello endpoints are accessible.

Upvotes: 0

Bruno Tremblay
Bruno Tremblay

Reputation: 776

This is fixed in the dev version I believe. It is was mainly a plumber openapi file generation problem as your endpoints would still respond if you used httr or curl to send a request.

devtools::install_github("rstudio/plumber")

Upvotes: 1

Related Questions