Plumber: plumb() a package

Created on 13 Feb 2016  Â·  9Comments  Â·  Source: rstudio/plumber

Is there a way to plumb an entire package? Basically creating the api in the package rather than an ad-hoc script plumber <- plumb(pkgname)

enhancement

Most helpful comment

That's a hefty :+1: cheers. Gotta be satisying closing those single digit issues :)

All 9 comments

I think that's an interesting idea. In general, I don't know that it would be useful or reasonable to write your package in such a way that it could behave as either exportable R code or a public API. While the selling point of plumber is that you don't _have_ to customize your existing functions to get an API, the reality is that an API of any real complexity would probably require some customization of the error codes, extra input sanitization, or some other additional tuning. So I think it's probably unrealistic to expect that a package author could just supplement their #' @export annotation with a plumber endpoint definition and call it a day.

But I think your point raises an interesting question. I could see two approaches which aren't mutually exclusive. Perhaps you can let me know if one or the other would be more useful for you.

  1. There could be a special convention that plumber adopts to identify/find API definitions in existing packages. So there's some plumber.R file that you provide in your inst/ directory that allows us to respond to a call like the example you gave (plumb(pkg="packagename")) gracefully. That's very doable.
  2. In the same way that there's a notion of a "data package" that doesn't necessarily have any interesting R functions that it exports, I suppose there could equally be a notion of an API package. This would just be a way to wrap up your API and all its dependencies (R code, data files, etc.) and distribute it as an R package. The advertised intent here would not be to both export code and offer an API in a single file (see point 1 for the recommended approach if that's your goal), but there might still be some value here as R packages are a lightweight way to encapsulate all the things some piece of R code needs to run.

The input sanitation can be managed with S3 for the most part. For example,
most of my functions take numeric/vector/data.frame arguments. So preparing
for api input is just a matter of setting an s3 method for a
myfun.character. Anything that comes from the web is already "character"
so it typically has to be converted anyways. It's actually pretty clean,
because it doesn't interfere with the non-api workings.

I suppose I'm less suggesting that a package be plumbable but moreso
suggesting that a directory of multiple files could be plumbable and all
function within the same API. Let's say I had a server with a pkg and
wanted to plumb a selection of functions within. It would be useful if
plumb knew how to scan a directory and include it appropriately.

Brandon Erik Bertelsen
647 287 1009
[email protected]
Linkedin http://www.linkedin.com/in/bbertelsen

On Sun, Feb 14, 2016 at 12:19 AM, Jeff Allen [email protected]
wrote:

I think that's an interesting idea. In general, I don't know that it would
be useful or reasonable to write your package in such a way that it could
behave as either exportable R code or a public API. While the selling point
of plumber is that you don't _have_ to customize your existing functions
to get an API, the reality is that an API of any real complexity would
probably require some customization of the error codes, extra input
sanitization, or some other additional tuning. So I think it's probably
unrealistic to expect that a package author could just supplement their #'
@export annotation with a plumber endpoint definition and call it a day.

But I think your point raises an interesting question. I could see two
approaches which aren't mutually exclusive. Perhaps you can let me know if
one or the other would be more useful for you.

  1. There could be a special convention that plumber adopts to
    identify/find API definitions in existing packages. So there's some
    plumber.R file that you provide in your inst/ directory that allows us
    to respond to a call like the example you gave (
    plumb(pkg="packagename")) gracefully. That's very doable.
  2. In the same way that there's a notion of a "data package" that
    doesn't necessarily have any interesting R functions that it exports, I
    suppose there could equally be a notion of an API package. This would just
    be a way to wrap up your API and all its dependencies (R code, data files,
    etc.) and distribute it as an R package. The advertised intent here would
    not be to both export code and offer an API in a single file (see point 1
    for the recommended approach if that's your goal), but there might still be
    some value here as R packages are a lightweight way to encapsulate all the
    things some piece of R code needs to run.

—
Reply to this email directly or view it on GitHub
https://github.com/trestletech/plumber/issues/32#issuecomment-183822974.

Fair point. I think that would be nice functionality.

I'd love to be able to combine that with https://github.com/trestletech/plumber/issues/36 so you can organize your API in modules that are independent. But being able to scan a directory and include all the files would be nice in and of itself.

+1 this would simplify the CICD pipeline for many

:+1:

Here's my 2 cents on packaging a plumber application as a package, which I think is a good idea: it is the standard way to "package" code in R, and it allows transparent dependency management with standard R tools:

In my little project I define a router [UPDATE] _and all endpoints programmatically_ within the only package function, which then creates routers based on an annotated script in the inst directory.

install.package(mypackage) installs all dependencies, library("mypackage"); mypackage::start() starts the app (or simply mypackage::start() after doing "Install and Restart" in RStudio), I'm relatively happy, except for #219.

Upvoting this. I'd love to deploy my application as a package, and I usually have a main() function called by Rscript. I'd like that main() function to plumb one or more .R files in the package, but this doesn't seem possible at the moment because .R files are not included when a package is installed.

So currently I have to resort to programmatically declare endpoints, but I'd love to see this improvement.

We took the stance of allowing for many plumber apis to be deployed within a single package.

As of plumber v1.0.0, you can call plumb_api(PKG, NAME) to plumb() the folder ./inst/plumber/NAME in the installed package PKG.

That's a hefty :+1: cheers. Gotta be satisying closing those single digit issues :)

Was this page helpful?
0 / 5 - 0 ratings