It is a list of lists, with the nested list giving you the "name" of the file and the "tmp_name", the location of the temporary file. For instance, to reference the uploaded file from the input tag named "FirstFile" you would use FILES$FirstFile$tmp_name. Here's a code snippet to copy the file to the '/usr/local/uploaded_files' directory:
destination <- file.path('/usr/local/uploaded_files',FILES$FirstFile$name)
file.copy(FILES$FirstFile$tmp_name,destination,overwrite=TRUE)
NOTE: the temporary files are deleted after the R handler completes handling the request. Thus, it is imperative that you copy/move this file to your desired location before the R handler returns.
5.5 SERVER.
As you can see from the below output, the SERVER variable contains a wealth of information about the incoming web request:
> str(SERVER)
List of 30
$ headers_in :List of 9
..$ Host : chr "localhost:8181"
..$ User-Agent : chr "Mozilla/5.0 (X11; U; Linux i686; en-US; ..."
..$ Accept : chr "text/xml,application/xml,application/x..."
..$ Accept-Language: chr "en-us,en;q=0.5"
..$ Accept-Encoding: chr "gzip,deflate"
..$ Accept-Charset : chr "ISO-8859-1,utf-8;q=0.7,*;q=0.7"
..$ Keep-Alive : chr "300"
..$ Connection : chr "keep-alive"
..$ Cache-Control : chr "max-age=0"
$ proto_num : int 1001
$ protocol : chr "HTTP/1.1"
$ unparsed_uri : chr "/brew/server.html/beetles/?foo=bar"
$ uri : chr "/brew/server.html/beetles/"
$ filename : chr "/home/hornerj/rapache/branches/rapache-1-0-br..."
$ canonical_filename: chr "/home/hornerj/rapache/branches/rapache-1-0-br..."
$ path_info : chr "/beetles/"
$ args : chr "foo=bar"
$ content_type : chr "text/html"
$ handler : chr "r-script"
$ content_encoding : NULL
$ range : NULL
$ hostname : chr "localhost"
$ user : NULL
$ header_only : logi FALSE
$ no_cache : logi FALSE
$ no_local_copy : logi FALSE
$ assbackwards : logi FALSE
$ status : int 200
$ method_number : int 0
$ eos_sent : logi FALSE
$ the_request : chr "GET /brew/server.html/beetles/?foo=bar HTTP/1.1"
$ method : chr "GET"
$ status_line : NULL
$ bytes_sent : num 0
$ clength : num 0
$ remaining : num 0
$ read_length : num 0
$ request_time :'POSIXct', format: chr "2007-08-15 11:11:49"
$ mtime :'POSIXct', format: chr "1969-12-31 18:00:00"
Here's a description of each list element:
headers_in list containing all the HTTP headers sent by the client.
proto_num Integer. Protocol version number of protocol; 1.1 = 1001
protocol Character. Protocol string, as given to us, or HTTP/0.9.
unparsed_uri Character. The URI without any parsing performed.
uri Character. The path portion of the URI.
filename Character. The name of the file with full path information.
canonical_filename Character. The true filename. Case and aliases/symbolic links have been resolved.
path_info Character. The suffix portion of the url after it has been matched to an asset that the web server knows about. An asset is either a file or an url defined by an Apache Location directive.
cmd_path Character. The path taken from the corresponding configuration directive.
args Character. The HTTP GET data extracted from this request.
content_type Character. The content-type for the current request.
handler Character. The handler string that we use to call a handler function.
content_encoding Character. How to encode the data.
range Character. The HTTP Response header named "Range:".
hostname Character. The server hostname.
user Character. If an HTTP authentication check was made, this gets set to the user name.
header_only Logical. HEAD request, as opposed to GET.
no_cache Logical. This response can not be cached.
no_local_copy Logical. There is no local copy of this response.
assbackwards Logical. HTTP/0.9, 'simple' request (e.g. GET /foo\n w/no headers). Developers have found this a useful way to internally redirect without headers.
status Integer. Status line.
method_number Integer value of GET, POST, etc.
eos_sent Logical. A flag to determine if the eos bucket has been sent yet.
the_request Character. First line of the request.
method Character. Request method (eg. GET, HEAD, POST, etc.)
status_line Character. Status line, if set by script.
bytes_sent Numeric. Number of bytes sent.
clength Numeric. The 'real' content length.
remaining Numeric. Remaining bytes left to read from the request body.
read_length Numeric. Number of bytes that have been read from the request body.
request_time POSIXct DateTime object. Time when the request started.
mtime POSIXct DateTime object. Last modified time of the requested resource .
5.6 Handler Return Values and HTTP Response Codes.
The following table describes variables that exist as integer vectors of length 1 in the R handler environment and are proper return values for R handlers. They consist of Apache module return values and HTTP Status Codes(see Status Code Definitions from RFC2616 for more info). The most reasonable response value and the one that most handlers will return is the value DONE.
name value description
DECLINDED -1 Module declines to handle
DONE -2 Module has served response completely.
OK -0 Module has handled this Apache response stage.
HTTP_CONTINUE 100
HTTP_SWITCHING_PROTOCOLS 101
HTTP_PROCESSING 102
HTTP_OK 200
HTTP_CREATED 201
HTTP_ACCEPTED 202
HTTP_NON_AUTHORITATIVE 203
HTTP_NO_CONTENT 204
HTTP_RESET_CONTENT 205
HTTP_PARTIAL_CONTENT 206
HTTP_MULTI_STATUS 207
HTTP_MULTIPLE_CHOICES 300
HTTP_MOVED_PERMANENTLY 301
HTTP_MOVED_TEMPORARILY 302
HTTP_SEE_OTHER 303
HTTP_NOT_MODIFIED 304
HTTP_USE_PROXY 305
HTTP_TEMPORARY_REDIRECT 307
HTTP_BAD_REQUEST 400
HTTP_UNAUTHORIZED 401
HTTP_PAYMENT_REQUIRED 402
HTTP_FORBIDDEN 403
HTTP_NOT_FOUND 404
HTTP_METHOD_NOT_ALLOWED 405
HTTP_NOT_ACCEPTABLE 406
HTTP_PROXY_AUTHENTICATION_REQUIRED 407
HTTP_REQUEST_TIME_OUT 408
HTTP_CONFLICT 409
HTTP_GONE 410
HTTP_LENGTH_REQUIRED 411
HTTP_PRECONDITION_FAILED 412
HTTP_REQUEST_ENTITY_TOO_LARGE 413
HTTP_REQUEST_URI_TOO_LARGE 414
HTTP_UNSUPPORTED_MEDIA_TYPE 415
HTTP_RANGE_NOT_SATISFIABLE 416
HTTP_EXPECTATION_FAILED 417
HTTP_UNPROCESSABLE_ENTITY 422
HTTP_LOCKED 423
HTTP_FAILED_DEPENDENCY 424
HTTP_UPGRADE_REQUIRED 426
HTTP_INTERNAL_SERVER_ERROR 500
HTTP_NOT_IMPLEMENTED 501
HTTP_BAD_GATEWAY 502
HTTP_SERVICE_UNAVAILABLE 503
HTTP_GATEWAY_TIME_OUT 504
HTTP_VERSION_NOT_SUPPORTED 505
HTTP_VARIANT_ALSO_VARIES 506
HTTP_INSUFFICIENT_STORAGE 507
HTTP_NOT_EXTENDED 510
Another suitable value to return from a handler is an object with S3 class of 'try-error'.
6. rApache Cookbook.
For a complete look at an rApache application, download the useR2007 application which uses Hmisc and brew for power and sample size calculations.
6.1 Exercising All Functionality
The following code exercises all rApache functionality by just echoing what was sent from the browser. Copy and paste the following code to a file and then set up apache with the following configuration. You should then be able to point your browser at http://example.com/rapachetest (replacing example.com with your own hostname).
#
# Place this in your Apache config file.
#
<Location /rapachetest>
SetHandler r-handler
RFileHandler /var/www/R/test.R
</Location>
#
# Copy and save this code to /var/www/R/test.R
#
hrefify <- function(title) gsub('[\\.()]','_',title,perl=TRUE)
scrub <- function(str){
if (is.null(str)) return('NULL')
if (length(str) == 0) return('length 0 string')
cat("\n<!-- before as.character: (",str,")-->\n",sep='')
str <- as.character(str)
cat("\n<!-- after as.character: (",str,")-->\n",sep='')
str <- gsub('&','&',str); str <- gsub('@','_at_',str);
str <- gsub('<','<',str); str <- gsub('>','>',str);
if (length(str) == 0 || is.null(str) || str == '')
str <- ' '
str
}
cl<-'e'
zebary <- function(i){
cl <<- ifelse(cl=='e','o','e')
cat('<tr class="',cl,'"><td>',scrub(i),'</td></tr>\n',sep='')
}
zeblist <- function(i,l){
cl <<- ifelse(cl=='e','o','e')
cat('<tr class="',cl,'"><td class="l">',names(l)[i],'</td><td>')
if(is.list(l[[i]]))
zebra(names(l)[i],l[[i]])
else {
if (length(l[[i]]) > 1)
zebary(l[[i]])
else
cat(scrub(l[[i]]))
}
cat('</td></tr>\n',sep='')
}
zebra <- function(title,l){
cat('<h2><a name="',hrefify(title),'"> </a>',title,'</h2>\n<table><tbody>',sep='')
ifelse(is.list(l),lapply(1:length(l),zeblist,l), lapply(l,zebary))
cat('</tbody></table>\n<br/><hr/>')
}
# Output starts here
setContentType("text/html")
if(is.null(GET)){
called <- 1
} else {
called <- as.integer(GET$called) + 1
}
setCookie('called',called,expires=Sys.time()+100)
cat('<HTML><head><style type="text/css">\n')
cat('table { border: 1px solid #8897be; border-spacing: 0px; font-size: 10pt; }')
cat('td { border-bottom:1px solid #d9d9d9; border-left:1px solid #d9d9d9; border-spacing: 0px; padding: 3px 8px; }')
cat('td.l { font-weight: bold; width: 10%; }\n')
cat('tr.e { background-color: #eeeeee; border-spacing: 0px; }\n')
cat('tr.o { background-color: #ffffff; border-spacing: 0px; }\n')
cat('</style></head><BODY><H1>Canonical Test for rApache</H1>\n')
cat('<form enctype=multipart/form-data method=POST action="?called=',called,'">\n',sep='')
cat('Enter a string: <input type=text name=name value=""><br>\n',sep='')
cat('Enter another string: <input type=text name=name value=""><br>\n',sep='')
cat('Upload a file: <input type=file name=fileUpload><br>\n')
cat('Upload another file: <input type=file name=anotherFile><br>\n')
cat('<input type=submit name=Submit>')
cat("<hr>\n")
zebra('CGI GET Data',GET)
zebra('CGI POST Data',POST)
zebra('Cookies',COOKIES)
if (!is.null(FILES)){
cat('<h2>Files Uploaded in POST Data</h2>\n')
for (n in names(FILES)){
zebra(paste("Form Variable",n),FILES[[n]])
}
}
zebra("SERVER Variables",SERVER)
cat("</BODY></HTML>\n")
DONE
6.2 Custom Error Messages
You can have handlers create custom HTTP error responses by using the setStatus() function. For instance, here's an example that sends a custom message for 500 "Internal Server Error":
handler <- function() {
setContentType("text/plain")
setStatus(500L)
cat("Hi, I'm a 'Fail Ale'!\n")
OK
}
If you liked this article, subscribe to the feed by clicking the image below to keep informed about new contents of the blog:
0 comments:
Post a Comment