文章阅读目录大纲
https://github.com/rsharp-lang/Rserver
在R语言之中,存在有一个FastRWeb的框架可以将R语言编写的脚本以http服务的方式运行于后台,供其他的语言进行调用。在R#语言之中,我也模仿着R语言之中的FastRWeb框架,创建了一个用于R#语言的web服务的程序包框架。
HTTP协议(Hypertext Transfer Protocol)是建立在TCP协议基础上的一种文件传输协议。本质上,HTTP协议是一种CS模式的TCP网络协议,因为存在客户端和服务器端;但是我们更加通常的将其称作为BS模式,即浏览器端对服务器端(虽然我们通常进行REST请求的客户端并不是浏览器)。我们的浏览器进行网页浏览就是进行基于HTTP协议的文件下载操作:例如打开一个网页就是下载一个html文件以及对应的image,css,js等附件文件
关于HTTP协议的基础,可以阅读文章《从零开始手撸一个Web服务器》
R#脚本语言的语法,大家可以阅读这两篇博客做一些初步的学习:《R#语言简明教程》,《R#语法教程之二》
使用Rhttp模块创建Web服务器
在R#语言之中,除了R#语言的Studio套件环境中的Rweb模块可以直接用来以http的方式执行我们的R#脚本代码。我们还可以通过使用Rhttp程序包模块所提供的Http相关的函数进行R#语言的web服务器的创建。在这里我们来主要介绍使用Rhttp的方式将R#脚本以Http服务的形式执行。
在Rhttp程序包模块之中,提供了一个http程序包,所以假若我们需要使用这个http程序包,会首先需要导入对应的模块,例如
imports "http" from "Rhttp";
之后R#的运行时环境中,就会导入了下面几个比较重要的可以用于进行Http操作相关的函数,给我们进行编程操作:
- http_socket 这个函数为我们创建了一个最基本的HTTP服务的驱动程序模块
- headers 这个函数可以为我们向HTTP的响应返回中添加默认的自定义消息头,例如版权信息等
- httpMethod 这个函数是必须要调用的,因为我们必须要通过这个函数向HTTP服务驱动程序之中添加对应的请求处理函数才会构建出一个完整的Web服务。
- listen 我们最后会需要通过这个函数来执行前面加载好的HTTP驱动程序模块。这个函数会需要传递一个端口号来监听来自浏览器的HTTP请求。
我们使用上面提到的R#脚本的HTTP服务的创建函数,可以通过下面的一段管道流程代码创建出一个相对完整的HTTP服务:
http::http_socket()
|> headers(
"X-Powered-By" = "R# web server",
"Author" = "xieguigang <xie.guigang@gcmodeller.org>",
"Github" = "https://github.com/rsharp-lang/Rserver",
"Organization" = "R# language <https://github.com/rsharp-lang/>"
)
|> httpMethod("GET", handleHttpGet)
|> httpMethod("POST", handleHttpPost)
|> httpMethod("PUT", [req, response] => writeLines("HTTP PUT test success!", con = response))
|> listen(port = httpPort)
;
可以看到,在上面所示的R#脚本代码示例之中,我们:
- 首先通过http_socket函数创建了一个HTTP服务的驱动程序;
- 接着添加自己的自定义HTTP消息头
- 再接着呢,通过httpMethod函数添加对应类型的请求处理函数
- 最后通过listen函数启动HTTP服务
处理HTTP请求
我们再前面的代码仅仅是创建了一个空的HTTP的服务框架,即里面是不包含有任何的Web请求的处理代码的。所以我们在这里介绍怎样通过httpMethod函数向我们的Web服务器框架之中添加对应的请求处理代码。
对于httpMethod函数而言,其主要接受三个参数:
- driver 参数为我们之前所创建的HTTP服务的驱动程序
- method 制定了当前所传入的处理函数所对应的目标HTTP方法,例如GET/POST/PUT等
- 最后最重要的一个参数就是process参数,我们必须要传递一个R#函数才行
例如
http::http_socket()
|> httpMethod("PUT", [req, response] => writeLines("HTTP PUT test success!", con = response))
;
上面的示例代码,我们通过一个lambda函数,直接向浏览器返回了一条固定的HTTP响应消息,例如下面是运行的效果
可以看到,我们传递的lambda函数已经正确的响应了来自于浏览器的PUT请求。
FastRWeb服务示意
在这里我为大家演示,如何通过GET请求执行一个R#脚本代码,用来实现一个类似于在R语言之中的FastRWeb服务的效果。
我们希望我们的R#脚本可以通过URL来执行对应的R#脚本文件,则我们会首先需要将URL逻辑地址转换为目标R#脚本在本地的物理路径,这个转换过程我们是会需要通过
函数来实现的,例如:getUrl
#' Route url as local R script file
#'
#' @param url the url object that parsed from the
#' http request.
#'
const router as function(url) {
`${webContext}/${ trim(url$path, ".") }.R`;
}
const R as string = router(getUrl(req));
上面的代码示例中的req对象就是来自于浏览器的HTTP请求数据,我们会需要通过getURL函数得到一个URL对象。在URL对象之中,我们这里主要是使用其path数据,例如
的path数据就是/ping。在添加了.R文件后缀名之后,这样子我们就可以将前面所提到的URL转换为一个本地的R#脚本文件路径。http://localhost/ping
我们可以通过
函数查看getURL得到的URL解析数据,例如:str
[1] "request from the browser client:"
List of 7
$ url : chr "http://localhost:80/ping?#"
$ path : chr "ping"
$ hostName : chr "localhost"
$ hash : <NULL>
$ query : ..list()
$ port : int 80
$ protocol : chr "http://"
接着我们就可以source所转换得到的目标R#脚本文件了。因为在R#环境之中,source函数会返回目标脚本的最后一段表达式的结果值,所以我们可以直接将source函数的返回结果作为HTTP的响应输出返回给浏览器端。在R#脚本之中,对于文本数据,几乎可以使用writeLines函数进行所有处理。我们在这里直接将返回给浏览器的HTTP响应作为目标文件,使用writeLines函数写入响应的结果。所以整个的脚本执行以及HTTP响应的处理代码可以如下所示:
# run R script and then send source evaluation result
# response back to the browser
writeLines(source(R), con = response);
假若我们的目标脚本文件找不到呢?别急,这个时候我们就可以使用
函数返回对应的HTTP错误代码了:httpError
response
|> httpError(404, `the required Rscript file is not found on filesystem location: '${ normalizePath(R) }'!`)
;
可以看到,上面的一段错误处理代码,如果我们尝试访问一个根本就不存在的R#脚本的话,错误处理代码已经正确的将错误反馈给了谷歌浏览器了。
服务器的ping/pang测试
在这里,我创建了一个最简单的脚本进行我们所创建的Web服务器的ping/pang测试。在这段脚本之中,仅包含有最简单的一个
字符串。因为source函数会将目标脚本的最后一条表达式的求值结果返回,所以我们的ping.R脚本肯定总是会返回pang!这个字符串给前面所示的writeLines函数的。pang!
# https://github.com/rsharp-lang/Rserver/blob/bf09d25923da4d3852702ae496d579bf408554cc/web.R/ping.R
"pang!";
将上面的脚本代码保存在ping.R文件之中,然后启动我们的R#网页服务器。在浏览器中请求http://localhost/ping
很好,我们自己通过R#脚本创建的Web服务器已经正确的向浏览器响应了一个
。一切都与我们所期待的那样,工作正常。pang!
命令行调用方法
上面的完整的脚本代码,大家可以进入到Github代码库中查看:https://github.com/rsharp-lang/Rserver/blob/main/script/http.R。这个写好的R#脚本的Web服务器的命令行使用方法非常简单,我们通过R#命令查看脚本的命令行使用方法:
可以看到这个脚本的使用方法非常的简单,就只需要告诉这个脚本我们的Web服务器监听哪一个端口号,需要执行的脚本的位置在哪一个文件夹之中就可以了。
- 【MZKit】简单自动化组织分区 - 2023年11月5日
- 【MZKit教程】质谱成像原始数据文件查看 - 2023年6月29日
- 生物序列图嵌入算法 - 2023年6月29日
No responses yet