Releases: rstudio/plumber
plumber v1.2.1
plumber v1.2.0
Breaking changes
- First line of endpoint comments interpreted as OpenAPI 'summary' field and subsequent comment lines interpreted as 'description' field. (@wkmor1 #805)
New features
-
Static file handler now serves HEAD requests. (#798)
-
Introduces new GeoJSON serializer and parser. GeoJSON objects are parsed into
sf
objects andsf
orsfc
objects will be serialized into GeoJSON. (@JosiahParry, #830) -
Add new Octet-Stream serializer. This is a wrapper around the Content Type serializer with type
application/octet-stream
. (#864) -
Update feather serializer to use the arrow package. The new default feather MIME type is
application/vnd.apache.arrow.file
. (@pachadotdev #849) -
Add parquet serializer and parser by using the arrow package (@pachadotdev #849)
-
Updated example
14-future
to usepromises::future_promise()
and added an endpoint that uses{coro}
to write simpler async /{promises}
code (#785) -
Add
path
argument topr_cookie()
allowing Secure cookies to define where they are served (@jtlandis #850)
Bug fixes
-
OpenAPI specification collision when using
examples
. (@meztez #820) -
Static handler returns Last-Modified response header. (#798)
-
OpenAPI response type detection had a scoping issue. Use serializer defined
Content-Type
header instead. (@meztez, #789) -
The default shared secret filter returns error responses without throwing an error. (#808)
-
Remove response bodies (and therefore the Content-Length header) for status codes which forbid it under the HTTP specification (e.g. 1xx, 204, 304). (@atheriel #758, @meztez #760)
-
Decode path URI before attempting to serve static assets (@meztez #754).
plumber v1.1.0
Breaking changes
-
Force json serialization of endpoint error responses instead of using endpoint serializer. (@meztez, #689)
-
When plumbing a Plumber file and using a Plumber router modifier (
#* @plumber
), an error will be thrown if the original router is not returned. (#738) -
options_plumber()
now requires that all options are named. If no option name is provided, an error with be thrown. (#746)
New features
-
Added option
plumber.trailingSlash
. This option (which is disabled by default) allows routes to be redirected to route definitions with a trailing slash. For example, if aGET
request is submitted to/test?a=1
with no/test
route is defined, but aGET
/test/
route definition does exist, then the original request will respond with a307
to reattempt againstGET
/test/?a=1
. This option will be enabled by default in a future release. This logic executed for before calling the404
handler. (#746) -
Added an experimental option
plumber.methodNotAllowed
. This option (which is enabled by default) allows for a status of405
to be returned if an invalid method is used when requesting a valid route. This logic executed for before calling the default404
handler. (#746) -
Passing
edit = TRUE
toplumb_api()
will open the API source file. (#699) -
OpenAPI Specification can be set using a file path. (@meztez #696)
-
Guess OpenAPI response content type from serializer. (@meztez #684)
-
Undeprecated
Plumber$run(debug=, swaggerCallback=)
and added the parameters forPlumber$run(docs=, quiet=)
andpr_run(debug=, docs=, swaggerCallback=, quiet=)
. Now, all four parameters will not produce lingering effects on thePlumber
router. (@jcheng5 #765)- Setting
quiet = TRUE
will suppress routine startup messages. - Setting
debug = TRUE
, will display information when an error occurs. Seepr_set_debug()
. - Setting
docs
will update the visual documentation. Seepr_set_docs()
. - Set
swaggerCallback
to a function which will be called with a url to the documentation, orNULL
to do nothing. Seepr_set_docs_callback()
.
- Setting
-
To update a
PlumberEndpoint
path after initialization, call the newPlumberEndpoint$setPath(path)
. This will update internal path matching meta data. (Active bindings were not used to avoid breaking changes.) (@blairj09 #770) -
PlumberStep
(andPlumberEndpoint
andPlumberFilter
) received a new field$srcref
and method$getFunc()
.$srcref
will contain the correspondingsrcref
information from original source file.$getFunc()
will return the evaluated function. (#782) -
Allow for spaces in
@apiTag
and@tag
when tag is surrounded by single or double quotes. (#685)
Bug fixes
-
Block parsing comments, tags and responses ordering match plumber api ordering. (#722)
-
Fixed bug where
httpuv
would return a status of500
with bodyAn exception occurred
if no headers were set on the response object. (#745) -
Fixed bug where all
pr_*()
returned invisibly. Now allpr_*()
methods will print the router if displayed in the console. (#740) -
When calling
Plumber$handle()
and defining a newPlumberEndpoint
,...
will be checked for invalid names. (@meztez, #677) -
/__swagger__/
now always redirects to/__docs__/
, even when Swagger isn't the selected interface. Useoptions(plumber.legacyRedirects = FALSE)
to disable this behavior. (@blairj09 #694) -
Fixed
available_apis()
bug where all packages printed all available APIs. (@meztez #708) -
Fixed Plumber
$routes
resolution bugs. Routes are now returned in lexicographical order. (@meztez #702) -
Plumber will now display a circular reference if one is found while printing. (#738)
-
Changed
future::plan()
frommultiprocess
tomultisession
in example API14-future
as "Strategy 'multiprocess' is deprecated in future (>= 1.20.0)". (#747) -
Setting options
plumber.docs.callback
toNULL
will also set deprecated but supported optionplumber.swagger.url
. (#766)
plumber v1.0.0
New features
Plumber router
-
Added support for promises in endpoints, filters, and hooks. This allows for multi-core execution when paired with
future
. Seeplumb_api("plumber", "13-promises")
andplumb_api("plumber", "14-future")
for example implementations. (#248) -
Added a Tidy API for more natural usage with magrittr's
%>%
. For example, a plumber object can now be initiated and run withpr() %>% pr_run(port = 8080)
. For more examples, see here (@blairj09, #590) -
Added support for
#' @plumber
tag to gain programmatic access to theplumber
router viafunction(pr) {....}
. Seesystem.file("plumber/06-sessions/plumber.R", package = "plumber")
and how it adds cookie support from withinplumber.R
. (@meztez and @blairj09, #568) -
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, callavailable_apis()
. (#631) -
Improved argument handling in Plumber Endpoint route definitions. See
system.file("plumber/17-arguments/plumber.R", package = "plumber")
to view an example with expected output andplumb_api("plumber", "17-arguments")
to retrieve the api. Improvements include:- The value supplied to
req
andres
arguments in a route definition are now always Plumber request and response objects. In the past, this was not guaranteed. (#666, #637) - To assist with conflicts in argument names deriving from different locations,
req$argsQuery
,req$argsPath
, andreq$argsBody
have been added to access query, path, andreq$body
parameters, respectively. For this reason, we suggest defining routes with onlyreq
andres
(i.e.,function(req, res) {}
) and accessing argument(s) under these new fields to avoid naming conflicts. (#637) - An error is no longer thrown if multiple arguments are matched to an Plumber Endpoint route definition. Instead, Plumber now retains the first named argument according to the highest priority match (
req$argsQuery
is 1st priority, thenreq$argsPath
, thenreq$argsBody
). (#666) - Unnamed elements that are added to
req$args
by filters or creatingreq$argsBody
will no longer throw an error. They will only be passed through via...
(#666)
- The value supplied to
OpenAPI
-
API Documentation is now hosted at
/__docs__
. Ifswagger
documentation is being used,/__swagger__
will redirect to/__docs__
. (#654) -
Added OpenAPI support for array parameters using syntax
name:[type]
and new typelist
(synonym df, data.frame). (@meztez, #532) -
Added user provided OpenAPI Specification handler to Plumber router. Use
$setApiSpec()
to provide a function to alter the Plumber generated OpenAPI Specification returned by Plumber router method$getApiSpec()
. This also affects/openapi.json
and/openapi.yaml
(#365)(@meztez, #562) -
Added
validate_api_spec()
to validate a Plumber API produces a valid OpenAPI Specification. (Experimental!) (#633)
Serializers
-
Added
as_attachment(value, filename)
method which allows routes to return a file attachment with a custom name. (#585) -
Serializer functions can now return
PlumberEndpoint
preexec
andpostexec
hooks in addition to aserializer
function by usingendpoint_serializer()
. This allows for image serializers to turn on their corresponding graphics device before the route executes and turn the graphics device off after the route executes. (#630) -
PNG, JPEG, and SVG image serializers have been exported in methods
serializer_png()
,serializer_jpeg()
, andserializer_svg()
respectively. In addition to these methods,serializer_tiff()
,serializer_bmp()
, andserializer_pdf()
have been added. Each graphics device serializer wraps aroundserializer_device()
, which should be used when making more graphics device serializers. (#630) -
New serializers
serializer_yaml()
: Return an object serialized byyaml
(@meztez, #556)serializer_csv()
: Return a comma separated value (@pachamaltese, #520)serializer_tsv()
: Return a tab separated value (#630)serializer_feather()
: Return a object serialized byfeather
(#626)serializer_text()
: Return text content (#585)serializer_cat()
: Return text content after callingcat()
(#585)serializer_print()
: Return text content after callingprint()
(#585)serializer_format()
: Return text content after callingformat()
(#585)serializer_svg()
: Return an image saved as an SVG (@pachamaltese, #398)serializer_headers(header_list)
: Method which sets a list of static headers for each serialized value. Heavily inspired from @ycphs (#455). (#585)serializer_write_file()
: Method which wrapsserializer_content_type()
, but orchestrates creating, writing serialized content to, reading from, and removing a temp file. (#660)
Body parsing
-
New request body parsers
parser_csv()
: Parse request body as a commas separated value (#584)parser_json()
: Parse request body as JSON (@meztez, #532)parser_multi()
: Parse multi part request bodies (@meztez, #532) and (#663)parser_octet()
: Parse request body octet stream (@meztez, #532)parser_form()
: Parse request body as form input (@meztez, #532)parser_rds()
: Parse request body as RDS file input (@meztez, #532)parser_text()
: Parse request body plain text (@meztez, #532)parser_tsv()
: Parse request body a tab separated value (#584)parser_yaml()
: Parse request body asyaml
(#584)parser_none()
: Do not parse the request body (#584)parser_yaml()
: Parse request body (@meztez, #556)parser_feather()
: Parse request body usingfeather
(#626)- Pseudo parser named
"all"
to allow for using all parsers. (Not recommended in production!) (#584)
-
The parsed request body values is stored at
req$body
. (#663) -
If
multipart/*
content is parsed,req$body
will contain named output fromwebutils::parse_multipart()
and add the parsed value to each part. Look here for access to all provided information (e.g.,name
,filename
,content_type
, etc). In addition,req$argsBody
(which is used for route argument matching) will contain a named reduced form of this information whereparsed
values (andfilename
s) are combined on the samename
. (#663)
Visual Documentation
-
Generalize user interface integration. Plumber can now use other OpenAPI compatible user interfaces like
RapiDoc
(https://github.com/mrin9/RapiDoc) andRedoc
(https://github.com/Redocly/redoc). Pending CRAN approbations, development R packages are available from https://github.com/meztez/rapidoc/ and https://github.com/meztez/redoc/. (@meztez, #562) -
Changed Swagger UI to use swagger R package to display the swagger page. (#365)
-
Added support for swagger for mounted routers (@bradleyhd, #274).
Security improvements
-
Secret session cookies are now encrypted using
sodium
.
All priorreq$session
information will be lost.
Please see?session_cookie
for more information.
(#404) -
Session cookies set the
HttpOnly
flag by default to mitigate cross-site scripting (XSS).
Please see?session_cookie
for more information.
(#404) -
Wrap
jsonlite::fromJSON
to ensure thatjsonlite
never reads
input as a remote address (such as a file path or URL) and attempts to parse
that. The only known way to exploit this behavior in plumber unless an
API were using encrypted cookies and an attacker knew the encryption key in
order to craft arbitrary cookies. (#325)
Breaking changes
-
When
plumb()
ing a file (orPlumber$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,
upgrading from Swagger Specification. (#365) -
Plumber router
$run()
method argumentsswagger
,swaggerCallback
anddebug
are now deprecated. User interface and url callback are now enabled by default and managed through Plumber router$setDocs()
,$setDocsCallback()
, and$setDebug()
methods and optionsplumber.docs
andplumber.docs.callback
. (@meztez, #562) -
plumb()
now returns an object of class"Plumber"
(previously"plumber"
). To check if an object is a Plumber router, use new methodis_plumber()
. (#653) -
PlumberStatic
objects now have a class of"PlumberStatic"
(previously"plumberstatic"
). (#653) -
The source files used in plumber must use the UTF-8 encoding if they contain
non-ASCII characters (@shrektan, #312,
#328). -
options(plumber.debug)
is not set anymore when running the plumber application. Instead retrieve the debug value using$getDebug()
on the Plumber router directly. Ex:function(req, res) { req$pr$getDebug() }
. (#639) -
PlumberEndpoint
's method$exec()
now has a shape of$exec(req, res)
(vs$exec(...)
). This allows for fine tune control over the arguments being sent to the endpoint function. -
When creating a
PlumberFilter
orPlumberEndpoint
, an error will be thrown ifexpr
does not evaluate to a function. (#666)
Deprecations
-
Shorthand serializers are now deprecated.
@html
,@json
,@png
,@jpeg
,@svg
should be replaced with the@serializer
syntax. Ex:@serializer html
or@serializer jpeg
(#630) -
plumber
R6 object has been deprecated and renamed toPlumber
.PlumberStatic
'sinherit
ed class has been updated toPlumber
. (#653) -
hookable
R6 object has been deprecat...
v0.4.6
- BUGFIX: Hooks that accept a
value
argument (postroute
,preserialize
,
andpostserialize
) now modify the incoming value as documented. - BUGFIX: The
postserialize
hook is now given the serialized data as its
value
parameter. - BUGFIX: properly handle cookie expiration values (#216).
- Add support for tags in Swagger docs (#230).
- Optional
swaggerCallback
parameter forrun()
to supply a callback function
for reporting the url for swagger page. - Add RStudio Project Template to package
v0.4.4
- Support Expiration, HTTPOnly, and Secure flags on cookies (#87). EDIT: see #216 which prevented expiration from working.
- BUGFIX: properly handle named query string and post body arguments in
mounted subrouters. - Added support for static sizing of images.
@png
and@jpeg
now accept a
parenthetical list of arguments that will be passed into thepng()
or
jpeg()
call. This enables annotations like
#' @png (width = 200, height=500)
. - Enable
ByteCompile
flag - Set working directory for DigitalOcean APIs.
- Respect
setErrorHandler
- BUGFIX: export
PlumberStatic
- Case-insensitive matching on
plumber.r
andentrypoint.r
when
plumb()
ing a directory. - Support query strings with keys that appear more than once
(#165) - Fix the validation error warning at the bottom of deployed Swagger files
which would have appeared any time yourswagger.json
file was hosted in
such a way that a hosted validator service would not have been able to access
it. For now we just suppress validation of swagger.json files. (#149) - Support for floating IPs in DNS check that occurs in
do_configure_https()
- Make adding swap file idempotent in
do_provision()
so you can now call that
on a single droplet multiple times. - Support an
exit
hook which can define a function that will be
evaluated when the API is interrupted. e.g.
pr <- plumb("plumber.R"); pr$registerHook("exit", function(){ print("Bye bye!") })
- Fixed bug in which a single function couldn't support multiple paths for a
single verb (#203).
v0.4.2
- Development version for 0.4.2. Will be working to move to even/odd release
cycles, but I had prematurely bumped to 0.4.0 so that one might get skipped,
making the next CRAN release 0.4.2.
v0.4.0
- BREAKING: Listen on localhost instead of listening publicly by default.
- BREAKING: We no longer set the
Access-Control-Allow-Origin
HTTP header to
*
. This was previously done for convenience but we've decided to prioritize
security here by removing this default. You can still add this header to any
route you want to be accessible from other origins. - BREAKING: Listen on a random port by default instead of always on 8000. This
can be controlled using theport
parameter inrun()
, or by setting the
plumber.port
option. - BREAKING: Removed
PlumberProcessor
class and replaced with a notion of
hooks. SeeregisterHook
andregisterHooks
on the Plumber router. - BREAKING:
addGlobalProcessor
method on Plumber routers now takes a list
which are added as hooks instead of a Processor. Note thatsessionCookie
has also been updated to behave accordingly, meaning that the convention of
pr$addGlobalProcessor(sessionCookie("secret", "cookieName"))
will continue
to work for this release. - BREAKING:
sessionCookie
now returns a list instead of a Processor. Note
thataddGlobalProcessor
has also been updated to behave accordingly,
meaning that the convention of
pr$addGlobalProcessor(sessionCookie("secret", "cookieName"))
will continue
to work for this release. - DEPRECATION: Deprecated the
addAssets
method on Plumber routers. Use
PlumberStatic
and themount
method to attach a static router. - DEPRECATION: Deprecated the
addEndpoint
method in favor of thehandle
method for Plumber routers. Removed support for theprocessors
,params
,
andcomments
parameters are no longer supported. - DEPRECATION: Deprecated the
addFilter
method on Plumber routers in favor
of the newfilter
method. Removed support for the processor parameter. - DEPRECATION: Deprecated the
addGlobalProcessor
method on Plumber routers. - The undocumented
setDefaultErrorHandler
method on Plumber routers now takes
a function that returns the error handler function. The top-level function
takes a single param nameddebug
which is managed by thedebug
parameter
in therun()
method. - Added support for
OPTIONS
HTTP requests via the@options
annotation. - Add support for
entrypoint.R
whenplumb()
ing a directory. If this file
exists, it is expected to return a Plumber router representing the API
contained in this directory. If it doesn't exist, the behavior is unaltered.
If bothplumber.R
andentrypoint.R
exist,entrypoint.R
takes precedence. plumb()
the current directory by default if no arguments are provided.- Added a
debug
parameter to therun
method which can be set toTRUE
in
order to get more insight into your API errors.