I want to send an xml
string to my Rook
web server. But when I use the POST
method of the Rook::Request
class to parse the POST
payload of my request, it puts the content into the name of the returned list. The corresponding list value is NA
. I use postForm
and the postfields
option of the RCurl
package to create my requests. A more detailed example follows below:
Put this into the file webserver.R
library(Rook)
s <- Rhttpd$new()
#set up web server app
s$add(
name="xml_example",
app=function(env) {
req <- Request$new(env)
#parse POST request
tmp=req$POST()
#create response
res <- Rook::Response$new()
#use dput and capture.output to return text of tmp
res$write(capture.output(dput(tmp)))
res$finish()
}
)
#start web server on port 9000
s$start(port=9000)
#we will start the web server via Rscript and NOT via RStudio
Sys.sleep(.Machine$integer.max)
The following can be executed via RStudio (Windows user might have to change some of the commands)
library(RCurl)
#start web server outside of RStudio! Do not forget to kill it later
system("Rscript webserver.R &")
#send POST request
postForm("http://127.0.0.1:9000/custom/xml_example",
.opts=list(postfields="<request>test</request>",
httpheader=c("content-type"="application/xml")))
This returns
#[1] "structure(list(`<request>test</request>` = NA),
# .Names = \"<request>test</request>\")"
As you can see, the xml
string is put into the list name. Not exactly what I was expecting. Apart from extracting the list name to get the xml
, how can this be done properly? Do I need to set options in Rook
or RCurl
?
BTW:
#do not forget to kill the webserver
system("ps aux|grep webserver.R")
#system("kill yourPIDhere")
It turned out to be a parsing error/feature within Rook
. Take for example the post request
postForm("http://127.0.0.1:9000/custom/xml_example",
.opts=list(postfields="xml=<request>test</request>",
httpheader=c("content-type"="application/xml")))
This gives the result
#[1] "structure(list(xml = \"<request>test</request>\"), .Names = \"xml\")"
As you can see, the Rook
parser assumes some sort of key=value
structure of the input. This is problematic for xml
s since they can include namespace definitions that use the =
sign (also when defining xml
versions and probably on other occasions).
Anyway, I turned away from Rook
as it can be made accessible to remote machines only via some hack (see http://jeffreyhorner.tumblr.com/post/33814488298/deploy-rook-apps-part-ii). This hack, BTW, does not work for me. I am using the plumber
package now - works like a charm! (https://github.com/trestletech/plumber)