Home > Net >  "Method Not Allowed" Error in R Plumber API
"Method Not Allowed" Error in R Plumber API

Time:12-25

I am creating an API for a random forest model deployment using the plumber package.

However, I always get the following error, which is probably about data loading:

"error": "405 - Method Not Allowed"

Below, I attached a reproducible example of my code with a simpler model. The error was the same.

library(plumber)
library(tidyverse)
library(jsonlite)
library(plumber)

set.seed(1234)
df <- tibble(x1 = rnorm(10),
             x2 = rnorm(10),
             epsilon = rnorm(10, mean = 0, sd = 1)) %>% 
  mutate(y = x1   3*x2   epsilon)%>% 
  select(y, x1, x2)

lm_model <- caret::train(y ~.,
                         data = df,
                         method = "lm")

#* Health Check - Is the API running?
#* @get /health-check
status <- function() {
  list(status = "All Good!",
       time = Sys.time())
}

#* 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()
}
#> function(req){
#>   cat(as.character(Sys.time()), "-",
#>       req$REQUEST_METHOD, req$PATH_INFO, "-",
#>       req$HTTP_USER_AGENT, "@", req$REMOTE_ADDR, "\n")
#>   
#>   forward()
#> }

#* Predict y
#* @filter /predict
function(req, res){
  if(grepl("predict", req$PATH_INFO)){
    req$predict_data <- tryCatch(jsonlite::fromJSON(req$postBody) %>% 
                                   as.data.frame(), 
                                 error = function(x){
                                   return(NULL)
                                 })
    
    if(is.null(req$predict_data)){
      res$status <- 400
      return(
        list(error = "No JSON file is found in the request")
      )
    }
    req$predicted_values <- predict(lm_model, req$predict_data)
  }
  forward()
}
#> function(req, res){
#>   if(grepl("predict", req$PATH_INFO)){
#>     req$predict_data <- tryCatch(jsonlite::fromJSON(req$postBody) %>% 
#>                                    as.data.frame(), 
#>                                  error = function(x){
#>                                    return(NULL)
#>                                  })
#>     
#>     if(is.null(req$predict_data)){
#>       res$status <- 400
#>       return(
#>         list(error = "No JSON file is found in the request")
#>       )
#>     }
#>     req$predicted_values <- predict(lm_model, req$predict_data)
#>   }
#>   forward()
#> }


#* Predict y for given data
#* @post /predict/values
function(req){
  y <- as.numeric(req$predicted_values)
  return(y)
  
}
#> function(req){
#>   y <- as.numeric(req$predicted_values)
#>   return(y)
#>   
#> }

I use API via Postman. I send my request in a JSON format and you can find an example below. I try to change formatting, but it did not work. The API works when I do not submit any data. The health check API works as well.

[
    {
        "x1" : 3,
        "x2" : 5
    }
]

What can be the problem? How can I solve it?

Thank you very much.

CodePudding user response:

According to Plumber’s changelog, as of Plumber 1.1.0:

[the] experimental option plumber.methodNotAllowed […] (which is enabled by default) allows for a status of 405 to be returned if an invalid method is used when requesting a valid route.

I see that you have just added the @post method to your /predict/value endpoint. Most probably you are calling the API with the GET method from Postmann. This would the return the error you specified.

You can fix this by either:

  1. Calling the API with the POST method from Postman, or
  2. Adding ‘@get /predict/values` to your predict function.

Hope this solves your problem.

  • Related