Introduction

Suppose you’ve developed a very useful algorithm or statistical model and you need to integrate it with some external system. Nowadays HTTP became de facto a lingua-franca for this kind of tasks.

In this article we will demonstrate how to use RestRserve to build a basic REST API.

Workflow overview

Generally RestRserve workflow consists of several major steps:

  1. Create application with Application$new()
  2. Create a function which follows RestRserve API:
    • should take 2 arguments - request and response as an input. request and response are instances of RestRserve::Request and RestRserve::Response. It is important to remember that both request and response are mutable objects.
    • should modify response in place or raise() exception in case of error
  3. Register this function as a handler for an endpoint
  4. Start application

1. Create application

library(RestRserve)
app = Application$new()

2. Define logic

For simplicity we will use Fibonacci number calculation as an algorithm we want to expose.

calc_fib = function(n) {
  if (n < 0L) stop("n should be >= 0")
  if (n == 0L) return(0L)
  if (n == 1L || n == 2L) return(1L)
  x = rep(1L, n)

  for (i in 3L:n) {
   x[[i]] = x[[i - 1]] + x[[i - 2]]
  }

  return(x[[n]])
}

Create function which will handle requests.

fib_handler = function(request, response) {
  n = as.integer(request$parameters_query[["n"]])
  if (length(n) == 0L || is.na(n)) {
    raise(HTTPError$bad_request())
  }
  response$set_body(as.character(calc_fib(n)))
  response$set_content_type("text/plain")
}

2. Register endpoint

app$add_get(path = "/fib", FUN = fib_handler)

3. Test endpoints

Now we can test our application without starting it:

request = Request$new(path = "/fib", parameters_query = list(n = 10))
response = app$process_request(request)

cat("Response status:", response$status)
#> Response status: 200 OK
cat("Response body:", response$body)
#> Response body: 55

It is generally a good idea to write unit tests against application. One can use a common framework such as tinytest.

4. Add OpenAPI description and Swagger UI

Generally it is a good idea to provide documentation along with the API. Convenient way to do that is to supply a openapi specification. This as simple as adding a yaml file as an additional endpoint:

yaml_file = system.file("examples", "openapi", "openapi.yaml", package = "RestRserve")
app$add_openapi(path = "/openapi.yaml", file_path = yaml_file)
app$add_swagger_ui(path = "/doc", path_openapi = "/openapi.yaml", use_cdn = TRUE)

5. Start the app

Now all is ready and we can start application with Rserve backend. It will block R session and start listening for incoming requests.

backend = BackendRserve$new()
backend$start(app, http_port = 8080)

6. Check it works

Check app can calculate fibonacci numbers:

Check out a swagger UI in the browser: http://localhost:8080/doc