Category Archives: Technical

WebSweave?

*** 2013-02-21 update: the WebSweave demo is no longer availble ***

A recent R-help post asks for examples of Sweave use for web appliations. I think there is very little out there. Below is a proof of concept for web-based Sweave-ing with rApache. But, it will soon be possible to do this with R's built-in web server. The idea is to treat an Sweave file as if it were a webpage with script elements. Here's the Sweave file (test.Rnw):

\documentclass{article}
\begin{document}
Below are GET variables passed in the URL:
<<>>=
if(exists("GET"))
    print(GET)
@
\begin{displaymath}
F(b) - F(a) = \int_a^b f(x)dx
\end{displaymath}
<<fig=TRUE, keep.source=TRUE>>=
     # From ?persp
     y <- x <- seq(-10, 10, length= 30)
     f <- function(x,y) { r <- sqrt(x^2+y^2); 10 * sin(r)/r }
     z <- outer(x, y, f)
     z[is.na(z)] <- 1
     persp(x, y, z, theta = 30, phi = 30, expand = 0.5)
@
\end{document}

where the GET variable is initialized by rApache and passed to a function that handles web requests (SweaveHandler; see below). When a web request is received, the GET variables are placed in the Sweave evaluation environment, Sweave is called, texi2dvi is called, and the browser is redirected to the resulting PDF file.

Below is the Sweave handler function that implements the Sweave part. The 'GET' variable is passed to this function in an environment, which is attached before Sweave is called.

Here are the contents of the SweaveHandler.R script:

SweaveHandler <- function(file, envir) {
    oldwd <- getwd()
    setwd(dirname(file))

    # Set up filenames
    rndname <- paste(sample(letters, 16, replace=TRUE), collapse='')
    bsefile <- sub("\\.[^\\.]*$", rndname, file)
    texfile <- paste(bsefile, ".tex", sep="")
    pdffile <- paste(bsefile, ".pdf", sep="")
    lnkurl  <- basename(pdffile)

    # Sweave!
    attach(envir, warn.conflicts=FALSE)
    Sweave(file, output = texfile, quiet=TRUE)
    detach(envir)
    tools::texi2dvi(texfile, clean=TRUE, pdf=TRUE)

    # Redirect to the newly created PDF
    setContentType("text/html; charset=UTF-8;")
    cat("<DOCTYPE! html><html><head>")
    cat(paste("<meta http-equiv=\"Refresh\" content=\"0;URL=",
        lnkurl, "\">", sep=""))
    cat("</head><body></body></html>")

    setwd(oldwd)

    # FIXME write binary data to stdout().
    # Would like to present PDF like this:
    # setContentType("application/pdf")
    # icon <- file(pdffile, "rb")
    # while(length(dat <- readBin(icon, "raw", 1024)) > 0)
    #     writeBin(dat, stdout())
    # flush(stdout())
    # close(icon) 
}

Apache and rApache must be configured to use the SweaveHandler function. The following are the contents of /etc/apache2/mods-available/rapache.conf:

<IfModule mod_R.c>
    ROutputErrors
    RSourceOnStartup "/path/to/SweaveHandler.R"
    <FilesMatch "\.Rnw$">
        SetHandler r-script
        Rhandler SweaveHandler
    </FilesMatch>
</IfModule>

Warning: This wass a proof-of-concept using R version 2.12.2, rApache version 1.1.14, texi2dvi version (GNU Texinfo 4.11) 1.104, and a host of other (TeX, pdfTeX, etc.) versioned software on an i686/Debian 5 machine. Due to the variety of interacting software, the setup above might not be 100% secure.