Skip to content

Commit

Permalink
Merge branch 'master' into rc-v1.0.0
Browse files Browse the repository at this point in the history
* master:
  Multipart body followup (#667)
  Copy in properly sized png logo
  Multipart Body parsing (#663)
  Add `serializer_write_file()` and add to some news entries (#660)
  Update logos to include a url. Add hex submitted to rstudio/hex-stickers
  • Loading branch information
schloerke committed Sep 1, 2020
2 parents 0e3edc7 + bb1d54e commit ae9db47
Show file tree
Hide file tree
Showing 34 changed files with 701 additions and 398 deletions.
1 change: 1 addition & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Imports:
sodium,
swagger (>= 3.20.3.99991),
magrittr,
mime,
lifecycle
LazyData: TRUE
ByteCompile: TRUE
Expand Down
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ export(serializer_text)
export(serializer_tiff)
export(serializer_tsv)
export(serializer_unboxed_json)
export(serializer_write_file)
export(serializer_yaml)
export(sessionCookie)
export(session_cookie)
Expand Down
57 changes: 33 additions & 24 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ plumber 1.0.0

#### Plumber router

* Added support for promises in endpoints, filters, and hooks. (#248)
* Added support for promises in endpoints, filters, and hooks. This allows for multi-core execution when paired with `future`. See `plumb_api("plumber", "13-promises")` and `plumb_api("plumber", "14-future")` for an example implementation. (#248)
* Added a Tidy API for more natural usage with magrittr's `%>%`. For example, a plumber object can now be initiated and run with `pr() %>% pr_run(port = 8080)`. For more examples, see [here](https://www.rplumber.io/articles/programmatic-usage.html) (@blairj09, #590)

* Added 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) {....}`. See `system.file("plumber/06-sessions/plumber.R", package = "plumber")` and how it adds cookie support from within `plumber.R`. (@meztez and @blairj09, #568)

* An error will be thrown if multiple arguments are matched to an Plumber Endpoint route definition.
While it is not required, it is safer to define routes to only use `req` and `res` when there is a possiblity to have multiple arguments match a single parameter name.
Use `req$argsPath`, `req$argsQuery`, and `req$argsPostBody` to access path, query, and postBody parameters respectively.
Use `req$argsPath`, `req$argsQuery`, and `req$argsBody` to access path, query, and postBody parameters respectively.
See `system.file("plumber/17-arguments/plumber.R", package = "plumber")` to view an example with expected output and `plumb_api("plumber", "17-arguments")` to retrieve the api.
(#637)

Expand Down Expand Up @@ -47,26 +47,31 @@ plumber 1.0.0
* `serializer_print()`: Return text content after calling `print()` (#585)
* `serializer_format()`: Return text content after calling `format()` (#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)

#### POST body parsing

* Added support for POST body parsing (@meztez, #532)

* New POST body parsers
* `parser_csv()`: Parse POST body as a commas separated value (#584)
* `parser_json()`: Parse POST body as JSON (@meztez, #532)
* `parser_multi()`: Parse multi part POST bodies (@meztez, #532)
* `parser_octet()`: Parse POST body octet stream (@meztez, #532)
* `parser_form()`: Parse POST body as form input (@meztez, #532)
* `parser_rds()`: Parse POST body as RDS file input (@meztez, #532)
* `parser_text()`: Parse POST body plain text (@meztez, #532)
* `parser_tsv()`: Parse POST body a tab separated value (#584)
* `parser_yaml()`: Parse POST body as `yaml` (#584)
* `parser_none()`: Do not parse the post body (#584)
* `parser_yaml()`: Parse POST body (@meztez, #556)
* `parser_feather()`: Parse POST body using `feather` (#626)
* pseudo parser named `"all"` to allow for using all parsers. (Not recommended in production!) (#584)
* `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 wraps `serializer_content_type()`, but orchestrates creating, writing serialized content to, reading from, and removing a temp file. (#660)

#### Body parsing

* Added support for request body parsing (@meztez, #532)

* 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 as `yaml` (#584)
* `parser_none()`: Do not parse the request body (#584)
* `parser_yaml()`: Parse request body (@meztez, #556)
* `parser_feather()`: Parse request body using `feather` (#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 from `webutils::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 where `parsed` values (and `filename`s) are combined on the same `name`. (#663)

#### Visual Documentation

Expand Down Expand Up @@ -132,6 +137,8 @@ plumber 1.0.0

* Documentation is updated and now presented using `pkgdown` (#570)

* New hex logo! Thank you @allisonhorst ! (#570)

* Added helper method `is_plumber(pr)` to determine if an object is a Plumber router. (#653)

* Added support for the `SameSite` Cookie attribute. (@chris-dudley, #640)
Expand Down Expand Up @@ -160,6 +167,8 @@ plumber 1.0.0

* Improve speed of `canServe()` method of the `PlumberEndpoint` class (@atheriel, #484)

* Get more file extension content types using the `mime` package. (#660)

### Bug fixes

* Handle plus signs in URI as space characters instead of actual plus signs (@meztez, #618)
Expand All @@ -175,7 +184,7 @@ plumber 1.0.0

* Fixed bug where functions defined earlier in the file could not be found when `plumb()`ing a file. (#416)

* A multiline POST body is now collapsed to a single line (@robertdj, #270 #297).
* A multiline request body is now collapsed to a single line (@robertdj, #270 #297).

* Bumped version of httpuv to >= 1.4.5.9000 to address an unexpected segfault (@shapenaji, #289)

Expand Down
136 changes: 85 additions & 51 deletions R/content-types.R
Original file line number Diff line number Diff line change
@@ -1,58 +1,92 @@
# FROM Shiny
# @author Shiny package authors
knownContentTypes <- list(
html='text/html; charset=UTF-8',
htm='text/html; charset=UTF-8',
js='text/javascript',
css='text/css',
png='image/png',
jpg='image/jpeg',
jpeg='image/jpeg',
gif='image/gif',
svg='image/svg+xml',
txt='text/plain',
pdf='application/pdf',
ps='application/postscript',
xml='application/xml',
m3u='audio/x-mpegurl',
m4a='audio/mp4a-latm',
m4b='audio/mp4a-latm',
m4p='audio/mp4a-latm',
mp3='audio/mpeg',
wav='audio/x-wav',
m4u='video/vnd.mpegurl',
m4v='video/x-m4v',
mp4='video/mp4',
mpeg='video/mpeg',
mpg='video/mpeg',
avi='video/x-msvideo',
mov='video/quicktime',
ogg='application/ogg',
swf='application/x-shockwave-flash',
doc='application/msword',
xls='application/vnd.ms-excel',
ppt='application/vnd.ms-powerpoint',
xlsx='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
xltx='application/vnd.openxmlformats-officedocument.spreadsheetml.template',
potx='application/vnd.openxmlformats-officedocument.presentationml.template',
ppsx='application/vnd.openxmlformats-officedocument.presentationml.slideshow',
pptx='application/vnd.openxmlformats-officedocument.presentationml.presentation',
sldx='application/vnd.openxmlformats-officedocument.presentationml.slide',
docx='application/vnd.openxmlformats-officedocument.wordprocessingml.document',
dotx='application/vnd.openxmlformats-officedocument.wordprocessingml.template',
xlam='application/vnd.ms-excel.addin.macroEnabled.12',
xlsb='application/vnd.ms-excel.sheet.binary.macroEnabled.12',
feather='application/feather',
rds='application/rds',
tsv="text/tab-separated-values",
csv="text/csv")
knownContentTypes <- c(
html = "text/html; charset=UTF-8",
htm = "text/html; charset=UTF-8",
js = "text/javascript",
css = "text/css",
png = "image/png",
jpg = "image/jpeg",
jpeg = "image/jpeg",
gif = "image/gif",
svg = "image/svg+xml",
txt = "text/plain",
pdf = "application/pdf",
ps = "application/postscript",
xml = "application/xml",
m3u = "audio/x-mpegurl",
m4a = "audio/mp4a-latm",
m4b = "audio/mp4a-latm",
m4p = "audio/mp4a-latm",
mp3 = "audio/mpeg",
wav = "audio/x-wav",
m4u = "video/vnd.mpegurl",
m4v = "video/x-m4v",
mp4 = "video/mp4",
mpeg = "video/mpeg",
mpg = "video/mpeg",
avi = "video/x-msvideo",
mov = "video/quicktime",
ogg = "application/ogg",
swf = "application/x-shockwave-flash",
doc = "application/msword",
xls = "application/vnd.ms-excel",
ppt = "application/vnd.ms-powerpoint",
xlsx = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
xltx = "application/vnd.openxmlformats-officedocument.spreadsheetml.template",
potx = "application/vnd.openxmlformats-officedocument.presentationml.template",
ppsx = "application/vnd.openxmlformats-officedocument.presentationml.slideshow",
pptx = "application/vnd.openxmlformats-officedocument.presentationml.presentation",
sldx = "application/vnd.openxmlformats-officedocument.presentationml.slide",
docx = "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
dotx = "application/vnd.openxmlformats-officedocument.wordprocessingml.template",
xlam = "application/vnd.ms-excel.addin.macroEnabled.12",
xlsb = "application/vnd.ms-excel.sheet.binary.macroEnabled.12",
feather = "application/feather",
rds = "application/rds",
tsv = "application/tab-separated-values",
csv = "application/csv",
json = "application/json",
yml = "application/yaml",
yaml = "application/yaml"
)

getContentType <- function(ext, defaultType='application/octet-stream') {
ct <- knownContentTypes[[tolower(ext)]]
if (is.null(ct)){
ct <- defaultType
getContentType <- function(ext, defaultType = 'application/octet-stream') {
ext <- tolower(ext)

ret <-
knownContentTypes[ext] %|%
mime::mimemap[ext] %|%
defaultType

ret[[1]]
}

cleanup_content_type <- function(type) {
if (length(type) == 0) return(type)

type <- tolower(type)

# remove trailing content type information
# "text/yaml; charset=UTF-8"
# to
# "text/yaml"
if (stri_detect_fixed(type, ";")) {
type <- stri_split_fixed(type, ";")[[1]][1]
}
return(ct)

type
}

get_fileext <- function(type) {
type <- cleanup_content_type(type)

all_content_types <- c(knownContentTypes, mime::mimemap)

type_to_ext <- setNames(names(all_content_types), all_content_types)

ret <- type_to_ext[type] %|% NULL
ret[[1]]
}

#' Request character set
Expand Down
Loading

0 comments on commit ae9db47

Please sign in to comment.