Layout of plumber api multiple functions

Hi
I have created some R APIs and to use in a docker container.

However, the first API is the only one that works.
For the second api, we get an error could not find function.

Is it possible to combine multiple api functions in one plumber file?
Is there a better way that what Im trying to do?

Here is an example of plumber.r

#* @apiTitle test
#* @apiDescription test


source("/code/api1.R")
source("/code/api2.R")


## ---- filter-logger
#* Log some information about the incoming request
#* @filter logger
function(req){
  cat(as.character(Sys.time()), "-",
      req$REQUEST_METHOD, req$PATH_INFO, "-",
      req$HTTP_USER_AGENT, "@", req$REMOTE_ADDR, "\n")
  
  forward()
}



#* @post /api1
#* @param Dataframe
function(req,res) {
  data <- tryCatch(jsonlite::parse_json(req$postBody, simplifyVector = TRUE),
                   error = function(e) NULL)
  if (is.null(data)) {
    res$status <- 400
    return(list(error = "No data submitted "))
  }
  req$results <- api1_function(data)
}


#* @post /api2
#* @param Dataframe
function(req,res) {
  data <- tryCatch(jsonlite::parse_json(req$postBody, simplifyVector = TRUE),
                   error = function(e) NULL)
  if (is.null(data)) {
    res1$status <- 400
    return(list(error = "No data submitted"))
  }
  req$results <- api2_function(data)
}

Entrypoint file

library(plumber)
r <- plumb("/code/plumber.R")
r$run(host='0.0.0.0', port=8000, swagger=TRUE)

Would really appreciate some help on this.
Thanks

Yes, it is possible.

Check your "/code/api2.R" file to make sure api2_function is correctly defined.

You can also use the internal plumber json parser, unless you absolutely want to handle json parsing error yourself.

plumber.R

#* @apiTitle test
#* @apiDescription test

source("./code/api1.R")
source("./code/api2.R")

## ---- filter-logger
#* Log some information about the incoming request
#* @filter logger
function(req){
  cat(as.character(Sys.time()), "-",
      req$REQUEST_METHOD, req$PATH_INFO, "-",
      req$HTTP_USER_AGENT, "@", req$REMOTE_ADDR, "\n")

  plumber::forward()
}

#* @post /api1
#* @param data:df
#* @serializer rds
function(dt = exemple) {
  api1_function(dt)
}

#* @post /api2
#* @param dt:df
#* @serializer text
function(dt = exemple) {
   api2_function(data)
}

exemple <- mtcars

./code/api1.R

api1_function <- summary

./code/api2.R

api2_function <- ncol
1 Like

Thank you for the response.
This is really helpful.

Trying to create a 3rd api, should the function be in an external file and reference a seperate r file?
e.g. api3 file = api3function <- function_in_external_file

Im having an issue when I pass JSON through to a function and get the error
Error in UseMethod("select"): no applicable method for 'select' applied to an object of class "environment"\n".

Is it necessary to use serializer json / unboxed json when passing json?

Apologies about this.
Ive spent a lot of time reading github posts etc and no success yet.

You do as you wish, my advice would be to package all the functions you want in an R package and use a library call.

Could you share the code that produce the error, plumber has a couple environment; req, res. Are you passing that directly?

select is most likely a dplyr function call.

To interactively interact with your plumber API call, put a browser() call at the top of your function() { browser(); ... }.

My apologies.
Using the serializer json and and changing parse_json to fromJson worked for me.*

Below works for api3

* @post /api3
#* @param dataframe
#* @serializer json
function(req,res) {

    data <- tryCatch(jsonlite::fromJSON(req$postBody, simplifyVector = TRUE),
                     error = function(e) NULL)
    if (is.null(data)) {
      res$status <- 400
      return(list(error = "No data submitted for slope calculation."))
    }
    req$results <- api3_function(data)
    
  }

Thank you for your time.
Ive marked the answer above as a solution.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.