[英]Access locally served files within an R session
In order to test the web capabilities of an R package I am writing, I'm attempting to serve a file locally use the httpuv
package so that I can run tests using an offline copy of the page.为了测试我正在编写的 R 包的 Web 功能,我尝试在本地使用
httpuv
包提供文件,以便我可以使用页面的离线副本运行测试。
However, curl
doesn't seem to want to play nice with httpuv
- specifically, when trying to read the hosted file using curl
(for example, with curl::curl()
or curl::curl_fetch_memory()
), the request hangs, and eventually times out if not manually interrupted.然而,
curl
似乎并不想与httpuv
配合得httpuv
——特别是,当尝试使用curl
读取托管文件时(例如,使用curl::curl()
或curl::curl_fetch_memory()
),请求挂起,如果没有手动中断,最终会超时。
# Serve a small page
server <- httpuv::startServer("0.0.0.0", port = 9359, app = list(
call = function(req) {
list(
status = 200L,
headers = list("Content-Type" = "text/html"),
body = "Some content..."
)
}
))
# Attempt to retrieve content (this hangs)
page <- curl::curl_fetch_memory(url = "http://127.0.0.1:9359")
httpuv::stopServer(server)
Once the server has been started, running curl -v 127.0.0.1:9359
at the terminal returns content as expected.服务器启动后,在终端运行
curl -v 127.0.0.1:9359
按预期返回内容。 Additionally, if I open a new instance of RStudio and try to curl::curl_fetch_memory()
in that new R session (while the old one is still open), it works perfectly.此外,如果我打开 RStudio 的新实例并尝试在该新 R 会话中
curl::curl_fetch_memory()
(而旧会话仍处于打开状态),它将完美运行。
Encouraged by that, I've been playing around with callr
for a while, thinking maybe it's possible to launch the server in some background process, and then continue as usual. callr
鼓舞,我一直在玩callr
一段时间,想也许可以在某个后台进程中启动服务器,然后像往常一样继续。 Unfortunately I haven't had any success so far with this approach.不幸的是,到目前为止,我用这种方法还没有取得任何成功。
Any insight or suggestions very much appreciated!非常感谢任何见解或建议!
Isn't it a great feeling when you can come back and answer a question you asked!当你能回来回答你问的问题时,是不是一种很棒的感觉!
From the httpuv::startServer()
documentation:从
httpuv::startServer()
文档:
startServer binds the specified port and listens for connections on an thread running in the background.
startServer 绑定指定的端口并在后台运行的线程上侦听连接。 This background thread handles the I/O, and when it receives a HTTP request, it will schedule a call to the user-defined R functions in app to handle the request.
这个后台线程处理 I/O,当它接收到一个 HTTP 请求时,它会调度调用 app 中用户定义的 R 函数来处理请求。 This scheduling is done with later().
这个调度是通过 later() 完成的。 When the R call stack is empty – in other words, when an interactive R session is sitting idle at the command prompt – R will automatically run the scheduled calls.
当 R 调用堆栈为空时——换句话说,当交互式 R 会话在命令提示符下处于空闲状态时——R 将自动运行计划调用。 However, if the call stack is not empty – if R is evaluating other R code – then the callbacks will not execute until either the call stack is empty, or the run_now() function is called.
但是,如果调用堆栈不为空——如果 R 正在评估其他 R 代码——那么回调将不会执行,直到调用堆栈为空或 run_now() 函数被调用。 This function tells R to execute any callbacks that have been scheduled by later().
该函数告诉 R 执行任何由 later() 安排的回调。 The service() function is essentially a wrapper for run_now().
service() 函数本质上是 run_now() 的包装器。
In other words, if we want to respond to requests as soon as they are received, we have to explicitly do so using httpuv::service()
.换句话说,如果我们想在收到请求后立即响应,我们必须使用
httpuv::service()
明确地这样做。 Something like the following does the trick!像下面这样的东西可以解决问题!
s <- callr::r_session$new()
on.exit(s$close())
s$call(function() {
httpuv::startServer("0.0.0.0", port = 9359, app = list(
call = function(req) {
list(
status = 200L,
headers = list("Content-Type" = "text/html"),
body = "Some content...")
)
}
))
while (TRUE) httpuv::service()
})
# Give the server a chance to start
Sys.sleep(3)
page <- curl_fetch_memory(url = "http://127.0.0.1:9359")
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.