Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add plumb_api() and available_apis() #631

Merged
merged 21 commits into from
Aug 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
a463097
Move all examples from `./inst/examples` to `./inst/plumber` for cros…
schloerke Aug 4, 2020
959fe8a
Rename `plumb_pkg()` to `plumb_api()`. Move all docker pointers from …
schloerke Aug 5, 2020
a1df57f
Add `plumb_api()` and `available_apis()`
schloerke Aug 5, 2020
0b35a19
Add test to test that all example apis work with `plumb()`
schloerke Aug 5, 2020
55b0b9f
moar docs! add news item
schloerke Aug 5, 2020
007f7ad
When plumbing a file, set the working directory to the file's dir.
schloerke Aug 5, 2020
5577a90
Add breaking change to the news item when plumbing a file and it's wo…
schloerke Aug 5, 2020
0c8b929
Infer the content type from the file extension in `include_file()`
schloerke Aug 5, 2020
532922b
fix tests
schloerke Aug 5, 2020
310f6f8
When plumbing a file, set the working directory to the file's directo…
schloerke Aug 5, 2020
b844d8c
When sourcing the entrypoint file, have the environment point to a gl…
schloerke Aug 5, 2020
bbb5abe
Fix tests
schloerke Aug 5, 2020
d5d5830
Apply suggestions from code review
schloerke Aug 5, 2020
e53cfcf
If no package is provided, return all available apis. If no name is p…
schloerke Aug 5, 2020
7f16c07
Document that the content_type can be NULL to disable the header
schloerke Aug 5, 2020
e00cd06
Use `split()` rather than duplicate subsetting
schloerke Aug 5, 2020
86d9a63
Use `available_apis()` and `plumb_api()` when validating plumber obje…
schloerke Aug 5, 2020
c2a26b5
Add a helper method to make sure all apis can be tested consistently
schloerke Aug 5, 2020
d2c6fec
Add `future` to make testing more complete
schloerke Aug 5, 2020
9bdcfda
allow test on linux as well
schloerke Aug 5, 2020
2ca0b93
merge master
schloerke Aug 6, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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