RestRserve-package {RestRserve} | R Documentation |
RestRserve: A Framework for Building HTTP API
Description
Allows to easily create high-performance full featured HTTP APIs from R functions. Provides high-level classes such as 'Request', 'Response', 'Application', 'Middleware' in order to streamline server side application development. Out of the box allows to serve requests using 'Rserve' package, but flexible enough to integrate with other HTTP servers such as 'httpuv'.
Details
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:
Create application with
Application$new()
Create a function which follows RestRserve API:
should take 2 arguments -
request
andresponse
as an input.request
andresponse
are instances ofRestRserve::Request
andRestRserve::Response
. It is important to remember that bothrequest
andresponse
are mutable objects.should modify
response
in place orraise()
exception in case of error
Register this function as a handler for an endpoint
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(.req, .res) { n = as.integer(.req$parameters_query[["n"]]) if (length(n) == 0L || is.na(n)) { raise(HTTPError$bad_request()) } .res$set_body(as.character(calc_fib(n))) .res$set_content_type("text/plain") }
You may have noticed strange .req
and .res
argument names. Starting
from RestRserve
v0.4.0 these “reserved” names allows to benefit from
autocomplete:
<img src=“https://cdn.rexy.ai/assets/req-res.gif” width=“640” style=“vertical-align:bottom”, alt=“request-response autocomplete gif”>
Technically .req
and .res
are just empty instances of ?Request
and
?Response
classes exported by RestRserve
in order to make
autocomplete work.
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:
openapi: 3.0.1 info: title: RestRserve OpenAPI version: '1.0' servers: - url: / paths: /fib: get: description: Calculates Fibonacci number parameters: - name: "n" description: "x for Fibonnacci number" in: query schema: type: integer example: 10 required: true responses: 200: description: API response content: text/plain: schema: type: string example: 5 400: description: Bad Request
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. Test it
Send request to calculate fibonacci number:
curl localhost:8080/fib?n=10
Check out a swagger UI in the browser: http://localhost:8080/doc
Author(s)
Maintainer: Dmitry Selivanov ds@rexy.ai (ORCID)
Authors:
Artem Klevtsov a.a.klevtsov@gmail.com (ORCID)
Other contributors:
David Zimmermann david_j_zimmermann@hotmail.com [contributor]
rexy.ai [copyright holder, funder]
See Also
Useful links:
Report bugs at https://github.com/rexyai/RestRserve/issues