19

I've seen lots of articles about consuming data in R from other RESTful API services, but I have really struggled to find any articles about the reverse. I'm interested in R being the server, and not the client. I'd like a Node.js app to call a RESTful API of an R-server so I can leverage specific analytical functions such as multi-seasonality forecasting. Anyone have any ideas?

jangorecki
  • 16,384
  • 4
  • 79
  • 160
Mark
  • 538
  • 6
  • 17
  • 3
    This is pretty much the most fleshed out option I've seen in this space but there are half a dozen alternatives: https://www.opencpu.org/ – Hansi Mar 04 '14 at 19:16
  • Any chance for generic `curl` interface? as described in the bounty. – jangorecki Apr 07 '15 at 22:26
  • Did you even look at the docs for OpenCPU? At the top of the API page, it explicitly states *"many of the sections below contain curl examples"*. – r2evans Apr 08 '15 at 05:54
  • @r2evans, I've played with opencpu a while ago (without success), don't know if it changed much since that time. Anyway I'm looking for a simple code to run in R, to just host the function which I can call with the curl. The examples are perfect, but there is no simple *run server from R* commands to type in R. If you know, please post as answer, deserved bounty will be yours! – jangorecki Apr 08 '15 at 08:31
  • Sorry, the comment about reading the docs was aimed at the comment that asked if it had a generic curl interface. I do think opencpu could fit the bill, though. Though not ideal, opencpu does start a single-process server for testing when you load the library interactively, and it still works remarkably well. – r2evans Apr 08 '15 at 13:41

2 Answers2

21

You can use httpuv to fire up a basic server then handle the GET/POST requests. The following isn't "REST" per se, but it should provide the basic framework:

library(httpuv)
library(RCurl)
library(httr)

app <- list(call=function(req) {

  query <- req$QUERY_STRING
  qs <- httr:::parse_query(gsub("^\\?", "", query))

  status <- 200L
  headers <- list('Content-Type' = 'text/html')

  if (!is.character(query) || identical(query, "")) {
    body <- "\r\n<html><body></body></html>"
  } else {
    body <- sprintf("\r\n<html><body>a=%s</body></html>", qs$a)
  }

  ret <- list(status=status,
              headers=headers,
              body=body)

  return(ret)

})

message("Starting server...")

server <- startServer("127.0.0.1", 8000, app=app)
on.exit(stopServer(server))

while(TRUE) {
  service()
  Sys.sleep(0.001)
}

stopServer(server)

I have the httr and RCurl packages in there since you'll probably end up needing to use some bits of both to parse/format/etc requests & responses.

sebastian-c
  • 15,057
  • 3
  • 47
  • 93
hrbrmstr
  • 77,368
  • 11
  • 139
  • 205
6

node-rio provides a way to talk to rserve (a TCP/IP server that allows the use of R functions) from node.js.

Here is an example of use (from the documentation):

var rio = require('rio');
rio.evaluate("as.character('Hello World')");
Christopher Louden
  • 7,540
  • 2
  • 26
  • 29
  • Thanks! I found that later yesterday as well and got the basic evaluate method to work. Having trouble on the sourceAndEvaluate method when I have to pass in variables. Can you help on something as simple as: testFunction <- function(a,b) { return a+b } ? I figured out how to step debugging through it sourcing this function by path, but I can't figure out how to parameterize data IO with the function. Any ideas? – Mark Mar 05 '14 at 20:40
  • Sorry, I am not too familiar with the actual working of node js. I mostly just know rserve. I would open up a new question. – Christopher Louden Mar 05 '14 at 20:48