rstudio / plumber

Turn your R code into a web API.
https://www.rplumber.io
Other
1.39k stars 256 forks source link

Not support closure #271

Closed renkun-ken closed 6 years ago

renkun-ken commented 6 years ago

Plumber does not seem to work with functions created as closure inside a function factory, which to some extent makes programming with the interface a bit harder and less flexible. The following is an example:

factory <- function(name) {
  function(n) {
    list(name = name, n = n)
  }
}

#* User1
#* @get /f1
f1 <- factory("user1")

#* User2
#* @get /f2
f2 <- factory("user2")

If user accesses the API, the following error occurs:

{"error":["500 - Internal server error"],
 "message":["Error in (function (n) : argument \"n\" is missing, with no default\n"]}
shizidushu commented 6 years ago

You need provide argument as query string in your api call if your function require it, such as add ?n=1

renkun-ken commented 6 years ago

Sorry, I mean visiting the page with ?n=1 does not work. The error message is still n is missing.

RemkoDuursma commented 6 years ago

But where is n in the inner function supposed to come from? The outer function does not pass it to the inner function.

factory <- function(name) {
  function(n) {
    list(name = name, n = n)
  }
}
schloerke commented 6 years ago

@renkun-ken

When working with files programmatically, it is best to dynamically define the plumber router, rather than statically. Plumber has been designed to run each function in a clean environment when sourced from a file.

Running your example and visiting /f1?n=1, I get the error: {"error":["500 - Internal server error"],"message":["Error in factory(\"user1\"): could not find function \"factory\"\n"]} .

We should define the plumber router as:

pr <- plumber::plumber$new()
pr$handle("GET", "/f1", factory("user1"))
pr$handle("GET", "/f2", factory("user2"))
pr$run()

When visiting /f1?n=1, I retrieve the output: {"name":["user1"],"n":["1"]}

schloerke commented 6 years ago

Can also set up the file to work like:

#* User2
#* @get /f2
f2 <- function(n) {
  factory("user2")(n)
}
schloerke commented 6 years ago

Closing for now as two alternatives were given. I do not see closure support working when plumbing a static file any time soon.