Site icon R-bloggers

Deploy Rook Apps: Part II

[This article was first published on Jeffrey Horner, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

In Part I, I described how you can deploy your Rook applications with rApache. This post describes how you can do it with R itself. But before we get into that, I’d like to explain the off-again on-again relationship Rook has had with CRAN, R’s package archive network.

Since inception (of Rook, not the movie), I wanted to give Rook the most flexibility possible, and that meant discovering how R’s internal web server worked. By inspecting the code from startDynamicHelp in the tools package, I discovered there were two basic calls to start and stop the server:

.Internal(startHTTPD("127.0.0.1", ports[i]))

and

.Internal(stopHTTPD())

but it turns out that inclusion of .Internal calls is a violation of CRAN’s Policy:

CRAN packages should use only the public API. Hence they should not use entry
points not declared as API in installed headers nor .Internal()l nor .Call()
etc calls to base packages. Such usages can cause packages to break at any
time, even in patched versions of R.

Understood. R-Core does a herculean job of maintaining the package repository with very little human and physical capital, and ensuring that R packages behave nicely from one R release to another is a task that all package authors should strive for. So, I yanked those calls out of Rook and play nicely by calling startDynamicHelp.

Unfortunately, that hobbles Rook in just the slightest way; it can no longer listen on any other IP address other than 127.0.0.1 … at least out of the box, but you as a Rook user are in full control of your R environment. That leads me to the following recipe for deploying a Rook app.

Yes, Using Only R, You Can Deploy A Rook App

So here’s a recipe I cooked up to circumvent R’s http environment. I don’t recommend doing this for production, but it’s nice to show a few friends and co-workers. This is an Rscript file which you can execute from the shell. It starts up Rook on port 8000 and will listen on the 0.0.0.0 IP address. That means it will listen on your loopback device as well as any other network device you have set up on your machine. If you want to be really savy, you could even change the myPort variable to 80, like a real web server! Just know that’s a priviledged port and will need root access.

The recipe adds the test application from the Rook package system files, and it’s easy to add more than one application if you like.

#!/usr/bin/env Rscript

library(Rook)

myPort <- 8000
myInterface <- "0.0.0.0"
status <- -1

# R 2.15.1 uses .Internal, but the next release of R will use a .Call.
# Either way it starts the web server.
if (as.integer(R.version[["svn rev"]]) > 59600) {
    status <- .Call(tools:::startHTTPD, myInterface, myPort)
} else {
    status <- .Internal(startHTTPD(myInterface, myPort))
}

if (status == 0) {
    unlockBinding("httpdPort", environment(tools:::startDynamicHelp))
    assign("httpdPort", myPort, environment(tools:::startDynamicHelp))

    s <- Rhttpd$new()
    s$listenAddr <- myInterface
    s$listenPort <- myPort

    # Change this line to your own application. You can add more than one
    # application if you like
    s$add(name = "test", app = system.file("exampleApps/RookTestApp.R", package = "Rook"))

    # Now make the console go to sleep. Of course the web server will still be
    # running.
    while (TRUE) Sys.sleep(24 * 60 * 60)
}

# If we get here then the web server didn't start up properly
warning("Oops! Couldn't start Rook app")

To leave a comment for the author, please follow the link and comment on their blog: Jeffrey Horner.

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.