Skip to content

Commit

Permalink
Add plumb_api() and available_apis() (#631)
Browse files Browse the repository at this point in the history
Co-authored-by: Barret Schloerke <schloerke@gmail.com>
Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
  • Loading branch information
3 people authored Aug 6, 2020
1 parent c7ce15a commit 58e84ac
Show file tree
Hide file tree
Showing 75 changed files with 579 additions and 214 deletions.
2 changes: 1 addition & 1 deletion .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
^\.travis\.yml$
^Dockerfile
^inst/analog-keys.R
^inst/examples/03-github/github-key.txt
^inst/plumber/03-github/github-key.txt
^\.httr-oauth
^docs
^scripts
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/docker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ jobs:
# always overwrite the latest version with the CRAN version
tags: "v0.4.6,latest"
ref: "v0.4.6"
extra_build_args: ",ENTRYPOINT_FILE='/usr/local/lib/R/site-library/plumber/examples/04-mean-sum/plumber.R'"

- name: GitHub
# 'next' tag signifies the _next_ release
Expand Down
4 changes: 3 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ Suggests:
later,
readr,
yaml,
feather
feather,
future
Remotes:
rstudio/swagger
RoxygenNote: 7.1.1
Expand All @@ -65,6 +66,7 @@ Collate:
'paths.R'
'plumb-block.R'
'plumb-globals.R'
'plumb.R'
'plumber-options.R'
'plumber-response.R'
'shared-secret-filter.R'
Expand Down
12 changes: 7 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ ARG R_VERSION=latest
FROM rocker/r-ver:${R_VERSION}
LABEL maintainer="barret@rstudio.com"

ARG PLUMBER_REF=master

# BEGIN rstudio/plumber layers
RUN apt-get update -qq && apt-get install -y --no-install-recommends \
git-core \
Expand All @@ -21,13 +19,17 @@ RUN install2.r remotes
## https://stackoverflow.com/a/55621942/591574
#ADD https://github.com/rstudio/plumber/commits/ _docker_cache

ARG PLUMBER_REF=master
RUN Rscript -e "remotes::install_github('rstudio/plumber@${PLUMBER_REF}')"

EXPOSE 8000

ENTRYPOINT ["R", "-e", "pr <- plumber::plumb(rev(commandArgs())[1]); pr$run(host='0.0.0.0', port=8000, swagger=TRUE)"]

CMD ["/usr/local/lib/R/site-library/plumber/examples/04-mean-sum/plumber.R"]
# Copy installed example to default file at ~/plumber.R
ARG ENTRYPOINT_FILE=/usr/local/lib/R/site-library/plumber/plumber/04-mean-sum/plumber.R
RUN cp ${ENTRYPOINT_FILE} ~/plumber.R

CMD ["~/plumber.R"]

# EOF rstudio/plumber layers

Expand All @@ -43,7 +45,7 @@ CMD ["/usr/local/lib/R/site-library/plumber/examples/04-mean-sum/plumber.R"]
# firefox http://localhost:8000/__swagger__/ &

# to run with your own api - mount your plumber.R file into the container like so:
# docker run -it -p 8000:8000 --rm -v ~/R/x86_64-pc-linux-gnu-library/4.0/plumber/examples/10-welcome/plumber.R:/api/plumber.R:ro --name myapi rstudio/plumber:latest /api/plumber.R
# docker run -it -p 8000:8000 --rm -v ~/R/x86_64-pc-linux-gnu-library/4.0/plumber/plumber/10-welcome/plumber.R:/api/plumber.R:ro --name myapi rstudio/plumber:latest /api/plumber.R
# then browse with
# curl http://localhost:8000/

Expand Down
6 changes: 5 additions & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
# Generated by roxygen2: do not edit by hand

S3method(format,plumber_available_apis)
S3method(print,plumber_available_apis)
export("%>%")
export(PlumberEndpoint)
export(PlumberStatic)
export(addSerializer)
export(as_attachment)
export(available_apis)
export(do_configure_https)
export(do_deploy_api)
export(do_forward)
Expand All @@ -31,6 +34,7 @@ export(parser_text)
export(parser_tsv)
export(parser_yaml)
export(plumb)
export(plumb_api)
export(plumber)
export(pr)
export(pr_cookie)
Expand Down Expand Up @@ -84,11 +88,11 @@ export(serializer_unboxed_json)
export(serializer_yaml)
export(sessionCookie)
import(R6)
import(crayon)
import(promises)
import(stringi)
importFrom(jsonlite,parse_json)
importFrom(jsonlite,toJSON)
importFrom(magrittr,"%>%")
importFrom(stats,runif)
importFrom(utils,installed.packages)
importFrom(webutils,parse_multipart)
10 changes: 8 additions & 2 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ plumber 1.0.0

### Breaking changes

* When `plumb()`ing a file (or `plumber$new(file)`), the working directory is set to the file's directory before parsing the file. When running the Plumber API, the working directory will be set to file's directory before running.(#631)

* Plumber's OpenAPI Specification is now defined using
[OpenAPI 3](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.3.md),
upgrading from Swagger Specification. (#365)
Expand Down Expand Up @@ -51,7 +53,7 @@ both UIs integration are available from https://github.com/meztez/rapidoc/ and h

* Added support for promises in endpoints, filters, and hooks. (#248)

* Add support for `#' @plumber` tag to gain programmatic access to the `plumber` router via `function(pr) {....}`. (@meztez and @blairj09, #568)
* Added support for `#' @plumber` tag to gain programmatic access to the `plumber` router via `function(pr) {....}`. (@meztez and @blairj09, #568)

* Added OpenAPI support for array parameters using syntax `name:[type]` and new type `list` (synonym df, data.frame). (@meztez, #532)

Expand All @@ -62,11 +64,15 @@ both UIs integration are available from https://github.com/meztez/rapidoc/ and h

* Documentation is presented using pkgdown (#570)

* Tidy API for easier programmatic usage (@blairj09, #590)
* Added a Tidy API for easier programmatic usage (@blairj09, #590)

* Added `plumb_api()` for standardizing where to locate (`inst/plumber`) and how to run (`plumb_api(package, name)`) plumber apis inside an R package. To view the available Plumber APIs, call `available_apis()`. (#631)


### Minor new features and improvements

* When calling `include_file()`, the `content_type` is automatically inferred from the file extension if `content_type` is not provided. (#631)

* Added `serializer_feather()` and `parser_feather()` (#626)

* When `plumb()`ing a file, arguments supplied to parsers and serializers may be values defined earlier in the file. (@meztez, #620)
Expand Down
4 changes: 2 additions & 2 deletions R/digital-ocean.R
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ do_provision <- function(droplet, unstable=FALSE, example=TRUE, ...){
install_firewall(droplet)

if (example){
do_deploy_api(droplet, "hello", system.file("examples", "10-welcome", package="plumber"), port=8000, forward=TRUE)
do_deploy_api(droplet, "hello", system.file("plumber", "10-welcome", package="plumber"), port=8000, forward=TRUE)
}

invisible(droplet)
Expand Down Expand Up @@ -121,7 +121,7 @@ droplet_capture <- function(droplet, command){

install_api <- function(droplet){
analogsea::droplet_ssh(droplet, "mkdir -p /var/plumber")
example_plumber_file <- system.file("examples", "10-welcome", "plumber.R", package="plumber")
example_plumber_file <- system.file("plumber", "10-welcome", "plumber.R", package="plumber")
if (nchar(example_plumber_file) < 1) {
stop("Could not find example 10-welcome plumber file", call. = FALSE)
}
Expand Down
8 changes: 4 additions & 4 deletions R/includes.R
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@ requireRmd <- function(fun_name){
#' @param file The path to the file to return
#' @param res The response object into which we'll write
#' @param content_type If provided, the given value will be sent as the
#' \code{Content-Type} header in the response.
#' `Content-Type` header in the response. Defaults to the contentType of the file extension.
#' To disable the `Content-Type` header, set `content_type = NULL`.
#' @export
include_file <- function(file, res, content_type){
include_file <- function(file, res, content_type = getContentType(tools::file_ext(file))){
# TODO stream this directly to the request w/o loading in memory
# TODO set content type automatically
lines <- paste(readLines(file), collapse="\n")
res$serializer <- "null"
res$body <- c(res$body, lines)

if (!missing(content_type)){
if (!is.null(content_type)) {
res$setHeader("Content-Type", content_type)
}

Expand Down
2 changes: 1 addition & 1 deletion R/openapi-spec.R
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@


#' Convert the endpoints as they exist on the router to a list which can
#' Convert the endpoints as they exist on the Plumber object to a list which can
#' be converted into a OpenAPI Specification for these endpoints
#' @noRd
endpointSpecification <- function(routerEndpointEntry, path = routerEndpointEntry$path) {
Expand Down
2 changes: 1 addition & 1 deletion R/plumb-block.R
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ evaluateBlock <- function(srcref, file, expr, envir, addEndpoint, addFilter, pr)
block <- plumbBlock(lineNum, file, envir)

if (sum(!is.null(block$filter), !is.null(block$paths), !is.null(block$assets), !is.null(block$routerModifier)) > 1){
stopOnLine(lineNum, file[lineNum], "A single function can only be a filter, an API endpoint, an asset or a router modifier (@filter AND @get, @post, @assets, @plumber, etc.)")
stopOnLine(lineNum, file[lineNum], "A single function can only be a filter, an API endpoint, an asset or a Plumber object modifier (@filter AND @get, @post, @assets, @plumber, etc.)")
}

# ALL if statements possibilities must eventually call eval(expr, envir)
Expand Down
Loading

0 comments on commit 58e84ac

Please sign in to comment.