Throwing Errors

9 views
Skip to first unread message

Brad Friedman

unread,
Sep 4, 2009, 12:05:29 AM9/4/09
to rapache
I am using RApache <a href="http://groups.google.com/group/rapache/
browse_thread/thread/e76f1bca3d14d871">to generate plots</a> for my
web application. Sometimes (for example bad user input) the plot
cannot be generated so I'd like to halt execution part way through the
script and send back a page containing the error. There are some hints
in the manual that this is possible but I'm having trouble getting it
going.

Below is a toy example to isolate my problem. Can anybody help me fix
it?

Thank you,

Brad

------

## Try to convert x argument to integer
x <- as.integer(GET$x)

if(is.null(GET$x) || is.na(x)) {
## If x was not supplied or doesn't convert well send error back to
user
## (this bit doesn't work right!)
setContentType("text/html")
cat("x was not supplied or didn't convert")
quit()
}

## x was succesfully converted. Make a plot with it.
setContentType("image/png")
tfn <- tempfile()
png(tfn, type="cairo", width=800, height=600)
plot(1:as.integer(GET$x))
dev.off()
sendBin(readBin(tfn, "raw", n=file.info(tfn)$size))
unlink(tfn)

DONE

Jeff Horner

unread,
Sep 4, 2009, 7:57:43 AM9/4/09
to rap...@googlegroups.com
Brad Friedman wrote:
> I am using RApache <a href="http://groups.google.com/group/rapache/
> browse_thread/thread/e76f1bca3d14d871">to generate plots</a> for my
> web application. Sometimes (for example bad user input) the plot
> cannot be generated so I'd like to halt execution part way through the
> script and send back a page containing the error. There are some hints
> in the manual that this is possible but I'm having trouble getting it
> going.
>
> Below is a toy example to isolate my problem. Can anybody help me fix
> it?
>
> Thank you,
>
> Brad
>
> ------
>
> ## Try to convert x argument to integer
> x <- as.integer(GET$x)
>
> if(is.null(GET$x) || is.na(x)) {
> ## If x was not supplied or doesn't convert well send error back to
> user
> ## (this bit doesn't work right!)
> setContentType("text/html")
> cat("x was not supplied or didn't convert")
> quit()
> }

Oh don't call quit(). That tries to shut down R!

Call return(DONE) or return(OK).

Jeff

Brad Friedman

unread,
Sep 7, 2009, 9:33:04 PM9/7/09
to rapache


> Oh don't call quit(). That tries to shut down R!
>
> Call return(DONE) or return(OK).


When I try this it gives me the following error:

Error in 1:as.integer(GET$x) : NA/NaN argument

In other words it continues running the script beyond the return()
statement. This particular example can be made to work by making the
second half of the script and else {} block. Is there some way to
prevent it from running the rest of the script?

Jeffrey Horner

unread,
Sep 9, 2009, 10:57:32 AM9/9/09
to rap...@googlegroups.com
Brad Friedman wrote on 09/07/2009 08:33 PM:
>
>
>> Oh don't call quit(). That tries to shut down R!
>>
>> Call return(DONE) or return(OK).
>
>
> When I try this it gives me the following error:
>
> Error in 1:as.integer(GET$x) : NA/NaN argument

Weird, So can you show us your code again? Where did you place the
return() statement?

Jeff
--
http://biostat.mc.vanderbilt.edu/JeffreyHorner

Brad Friedman

unread,
Sep 9, 2009, 4:00:32 PM9/9/09
to rapache

Hi, Jeff

Here's the test.R file.

I'm also copying the RApache-related part of my httpd.conf file in
case it might be relevant (further below).

Thanks for your help!

Brad

--------------------------------------------------------------

## Try to convert x argument to integer
x <- as.integer(GET$x)

if(is.null(GET$x) || is.na(x)) {
## If x was not supplied or doesn't convert well send error back to
user
## (this bit doesn't work right!)
setContentType("text/html")
cat("x was not supplied or didn't convert")
return(DONE)
}

## x was succesfully converted. Make a plot with it.
setContentType("image/png")
tfn <- tempfile()
png(tfn, type="cairo", width=800, height=600)
plot(1:as.integer(GET$x))
dev.off()
sendBin(readBin(tfn, "raw", n=file.info(tfn)$size))
unlink(tfn)

DONE


-----------------------------------------------------------

LoadModule R_module /usr/lib/apache2/modules/mod_R.so
ROutputErrors
REvalOnStartup "library(RMySQL)"
<Location /R/>
SetHandler r-script
RHandler sys.source
</Location>

Jeff Horner

unread,
Sep 10, 2009, 8:17:02 AM9/10/09
to rap...@googlegroups.com
Brad Friedman wrote:
>
> Hi, Jeff
>
> Here's the test.R file.
>
> I'm also copying the RApache-related part of my httpd.conf file in
> case it might be relevant (further below).
>
> Thanks for your help!

Two things:

1. Using return() from sys.source() doesn't work, so you will want to
wrap your code in an if-else statement like so:
--------------------------------------
if(is.null(GET$x) || is.na(x)) {
## If x was not supplied or doesn't convert well send error back
to user
## (this bit doesn't work right!)
setContentType("text/html")
cat("x was not supplied or didn't convert")
} else {
## x was succesfully converted. Make a plot with it.
setContentType("image/png")
tfn <- tempfile()
png(tfn, type="cairo", width=800, height=600)
plot(1:as.integer(GET$x))
dev.off()
sendBin(readBin(tfn, "raw", n=file.info(tfn)$size))
unlink(tfn)
}

DONE
---------------------------------

I should have known better than to suggest return() to you before. It's
just that I was confused about the context in which you were creating
your application.

2. It's more intuitive to use the <Directory> directive rather than the
<Location> directive when using the 'r-script' handler like so:

<Directory /home/hornerj/rapache-1.1.8/test/source>
SetHandler r-script
RHandler sys.source
</Directory>

This means that every file under that directory will be treated as an R
script handled through sys.source(). With your <Location> directive, it
means every url that starts with /R/ will be treated as such and you may
or may not want that to happen. Just something to be aware of...

The whole business with the handlers 'r-script' and 'r-handler' with
RHandler and RFile is quite confusing but leads to a variety of ways to
structure your application. I'm hoping over time users will come up with
better ways to define this in the apache config.

Jeff

Brad Friedman

unread,
Oct 20, 2009, 11:40:47 PM10/20/09
to rapache

In case anybody else is having this problem I thought I'd post the
solution I'm working with now---but probably Jeff can suggest a better
one!

I don't the having to wrap all the exits in if-else statements because
I want to use this for error-reporting, so I will potentially have
many places that the script could short-circuit---so that would get
really complicated.

Instead now I am just going to wrap the whole script in a function.
Then I just call the function and then return OK for the whole
scripts---but within the function I can short-circuit with return():

handler <- function() {

x <- as.integer(GET$x)

if(is.null(GET$x) || is.na(x)) {
setContentType("text/html")
cat("x was not supplied or didn't convert")
return() ### THIS WORKS!
}

setContentType("image/png")
tfn <- tempfile()
png(tfn, type="cairo", width=800, height=600)
plot(1:as.integer(GET$x))
dev.off()
sendBin(readBin(tfn, "raw", n=file.info(tfn)$size))
unlink(tfn)
}

handler()
DONE

Jeffrey Horner

unread,
Oct 21, 2009, 4:07:19 PM10/21/09
to rap...@googlegroups.com
Hey Brad,

If this handler() function will only be referenced by one URL, then you
could set up the apache config like this:

<Location /some/url>
SetHandler r-handler
RFileHandler /path/to/file.R::handler
</Locaiton>

and modify your handler function to return DONE, and don't forget to
make your short-circuit code return an appropriate value as well.


Jeff
--
http://biostat.mc.vanderbilt.edu/JeffreyHorner

Reply all
Reply to author
Forward
0 new messages