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

Work in progress, combined PR #536

Closed
wants to merge 100 commits into from
Closed

Conversation

meztez
Copy link
Collaborator

@meztez meztez commented May 17, 2020

I combined all the work done into one PR, it was getting hard to track all work across different branches.

This is still a work in progress.

What this branch contains:

  • document options with roxygen like shiny
  • ignore req, res, data in function args detection
  • parser yaml / serializer
  • redoc
  • mount openapi.yaml
  • Distinguish between 404 and 405 http error
  • Distinguish between openapi and swagger in objects names
  • Set body max size with getOption('plumber.maxRequestSize', 0)
  • rename some files to better match the purpose of their content
  • Add yaml dep in case we want to suppoer fromOpenAPI yaml format
  • Modular body parsing, more like serializers
  • R6 Documentation
  • toOpenAPI from a file or plumber router
  • Support array parameters, files, object as plumber type
  • Fix OpenAPI api url when referer from same domain (empty)
  • Fix tests on non UTF-8 platform / Windows
  • Add libsodium-dev dep
  • Switch to xenial-cran35, trusty-cran35
  • Fix doc / imports to avoid :: on moderatly used functions
  • Perf improvement getCharacterSet
  • Fix isNaOrNULL when x is c(NULL, value)
  • Add expression args detection to openAPI specs
  • Fix image serializer execution position
  • Switch to remotes instead of devtools
  • Remove non-test output from test outputs

Still to be done:

  • http error generalization ??
  • fromOpenAPI
  • modular plumb methods for plumbing files / custom tags
  • parser text/csv / serializer
  • Proof read docs once development stabilizes

Breaking:

swagger/swaggerCallback in run method of PlumberRouter :

  • Now there is a ui and callback param
  • ui can be TRUE, FALSE or character vector
  • It supports "Swagger" and "Redoc" (meztez/redoc, CRAN pending)
  • callback has the same function as before (RStudio)
  • PlumberRouter gains customSpec field for Custom OpenAPI (expect named list)
  • Removed deprecated code for major version release 5.0.0
  • Removed requestBody from req env

Why I broke stuff : I felt it was needed for 5.0.0 to make a clear split between the UIs (Swagger, Redoc) and OpenAPI specifications. You don't need to run a router to get the specs with your custom definitions in this PR. I also think the run method had too much clutter.
Custom definitions are applied using utils::modifyList and overwrite default plumber spec. This is a bit different than prior approach.

Open questions to maintainers:

Body parsing

  • Which dep? mimes, webutils, or write multipart parser?
  • When picking a body parser, what should happen when picker finds multiple matches? Currently uses the first indexed one
  • Normally nothing should read rook.input before postBodyFilter, rewind to be safe if change are made elsewhere?
  • Is it memory wise to store the entire body in req$requestBody when it contains whole files

Decide what to do with files sent to API

  • Should plumber let the user delete them?
  • Handling maxfilesize limit, with option ok?
  • Should it even write file sent to disk?
  • What should be the default max request body size (0 Unlimited?)

Misc

  • Get rid of Legacy methods in Plumber R6 object?
  • in R6 Class PlumberStep, should getPathParams, getTypedParams and getFunctParams return all in the format? Maybe a name change in methods here could help distinguish between getTypedParams and getPathParams?
  • Bump to R 4.0.0 already in droplet?

Tremblay added 5 commits June 12, 2020 11:46
Merge remote-tracking branch 'upstream/master' into to_from_openapi

# Conflicts:
#	R/plumber-response.R
#	man/plumber.Rd
Merge branch 'rm_pr_link_news' into to_from_openapi

# Conflicts:
#	NEWS.md
@schloerke
Copy link
Collaborator

@meztez Do you mind remerging the master branch? (Sometime before this Monday)
Thank you!

@meztez
Copy link
Collaborator Author

meztez commented Jun 18, 2020

I was thinking about splitting this one in smaller chunk since you merge #532 if it is ok with you. yes before monday.

@schloerke
Copy link
Collaborator

Even better! 🙌

Bruno Tremblay added 11 commits June 21, 2020 22:12
Merge remote-tracking branch 'upstream/master' into to_from_openapi

# Conflicts:
#	DESCRIPTION
#	NAMESPACE
#	NEWS.md
#	R/content-types.R
#	R/globals.R
#	R/plumb-block.R
#	R/plumber.R
#	R/post-body.R
#	R/query-string.R
#	R/swagger.R
#	inst/examples/15-swagger-spec/entrypoint.R
#	man/addParser.Rd
#	man/parsers.Rd
#	tests/testthat/test-postbody.R
#	tests/testthat/test-swagger.R
Comment on lines +2 to +3
dataTypesInfo <- list()
dataTypesMap <- list()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May we use a more specific name? Maybe apiTypesInfo? (sub("data", "api", .))

It's a lot of name changes, but it helps when reading to supply context

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was in the process a decoupling the mountui part and de renaming, reorganizing part.

Also wondering what would be a good name for dataType.

It refers to OpenAPI data types. If you think apiTypes would work, I'm down for it.

Don't worry about replacing stuff. Naming things is the hardest part.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also wondering what would be a good name for dataType.

apiType helps a lot. It lets me know that it's prolly a string value describing the OpenAPI Spec type.

dataType feels like an output of typeof() or something unrelated to OpenAPI

I was in the process a decoupling the mountui part and de renaming, reorganizing part.

Great! Feel free to make those changes there. 😄

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am hoping to refer to all things OpenAPI by using api in the variable name.

(Things with plumber are pr or router.)

Comment on lines +272 to +275
ui = interactive(),
debug = interactive(),
swaggerCallback = getOption('plumber.swagger.url', NULL)
callback = getOption('plumber.ui.callback', getOption('plumber.swagger.url', NULL)),
...
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we change the order? And set ui to TRUE.

..., 
ui = TRUE,
debug = interactive(),
callback = ....

Comment on lines +810 to +818
if (is.list(self$customSpec)) {
ret <- utils::modifyList(ret, self$customSpec)
}
ret <- removeNaOrNulls(ret)

ret
},
#' @description Retrieve openAPI file
openAPIFile = function() {
self$swaggerFile()
},
#' @field customSpec A list of custom spec to overlay over openAPI spec
#' generated from a plumber router.
customSpec = NULL,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than using a static object, I'd like to supply a function directly.

#### in the private defs
    apiHandler = force,
    #' @description Add a function to customize what is returned in `$apiSpec()`. 
    #' @param api_fun This function should accept an OpenAPI Specification autogenerated by `plumber`.  It should return a list object in valid OpenAPI Specification format. This will not be validated.
    setApiHandler = function(api_fun = force) {
      # allow null values
      if (!is.null(api_fun)) {
        stopifnot(is.function(api_fun))
      }
      private$apiHandler <- api_fun
    }

# Lay those over the default globals so we ensure that the required fields
# (like API version) are satisfied.
#' @description Retrieve OpenAPI specification
openAPISpec = function() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's a little shorter and less confusing with the caps

Suggested change
openAPISpec = function() {
apiSpec = function() {

In the documentation, we can always refer to it as the OpenAPI Specification function


# Lay those over the default globals so we ensure that the required fields
# (like API version) are satisfied.
#' @description Retrieve OpenAPI specification
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They seem to like Specification to be capitalized

The OpenAPI Specification (OAS) defines ....

Suggested change
#' @description Retrieve OpenAPI specification
#' @description Retrieve OpenAPI Specification


### Legacy/Deprecated
#' @description Retrieve OpenAPI specification (deprecated and will be removed in a coming release)
openAPIFile = function() {
self$openAPISpec()
Copy link
Collaborator

@schloerke schloerke Jun 22, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
self$openAPISpec()
warning("`$openAPIFile()` has been deprecated in v1.0.0 and will be removed in a coming release. Please use `$apiSpec()`.")
self$openAPISpec()

self$openAPISpec()
},
#' @description Retrieve OpenAPI specification (deprecated and will be removed in a coming release)
swaggerFile = function() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
swaggerFile = function() {
warning("`$swaggerFile()` has been deprecated in v1.0.0 and will be removed in a coming release. Please use `$apiSpec()`.")
swaggerFile = function() {

@@ -1071,7 +985,7 @@ plumber <- R6Class(
private$ends[[preempt]] <- c(private$ends[[preempt]], ep)
},

swaggerFileWalkMountsInternal = function(router, parentPath = "") {
routerSpecificationInternal = function(router, parentPath = "") {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for renaming these variables! 😃

@meztez
Copy link
Collaborator Author

meztez commented Jun 23, 2020

By adding #562, this one can die in peace. Goodbye shemera PR.

@meztez meztez closed this Jun 23, 2020
@meztez meztez deleted the to_from_openapi branch June 24, 2020 23:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants