验证R REST API中的输入

时间:2016-07-26 17:20:33

标签: r rest

我正在构建一个R REST API,我可以在其中公开一些R函数/模型。

我从这个问题开始: Suggestions needed for building R server REST API's that I can call from external app?

添加了一些额外的处理,并开始使用httpuv的守护程序服务器功能。

它已经起作用了。我担心的是这样做是否安全。我怎么能确定我对不正确的请求做出了正确的回应,并且一个人无法意外/恶意地注入代码。

现在,他们可以使用http://IPADDRESS:PORT/FUNCTION?a=VALUE&b=VALUE

调用api

在所有文本解析过程中是否有一种好方法可以验证我的输入?

(这都在我们的内部网络上,所以我不太关心恶意方面,但我真的很想知道这里的限制)

这是“这里有龙”的情况吗?

CODE:

library(httpuv)
library(RCurl)
library(httr)
library(jsonlite)

从一些功能开始:

#################################################################################
# API Functions
#################################################################################
APIoperations <-
  list(
    Add = function(a,b) a + b,
    Subtract = function(a,b) a - b,
    Multiply = function(a,b) a*b,
    Divide = function(a,b) a/b
  )

做一些验证:

#################################################################################
# Check if Operation is Supported
#################################################################################
validateOperation <- function(op) {
  if(op %in% names(APIoperations)) {
    op
  } else {
    # DO OTHER THINGS HERE
    # LOG, etc...
    'Unsupported'
  }
}

错误格式:

#################################################################################
# General Error Format
#################################################################################
returnError <- function(error = '',
                        status = 500L,
                        headers = list('Content-Type' = 'text/html'),
                        body = paste('\r\n<html><body>',error,'</body></html>')) {
  list(status = status,
       headers = headers,
       body = body)
}

然后是我的实际服务器逻辑:

#################################################################################
#################################################################################
# Start Server Logic
#################################################################################
#################################################################################
app <-
  list(call =
         function(req) {
           #################################################################################
           # Grab and Parse Query
           # Only include acceptable characters

           query <- req$QUERY_STRING

           if(validateOperation(gsub('[[:punct:]]','',req$PATH_INFO)) == 'Unsupported') {
             return(list(status=501L,
                         headers=list('Content-Type' = 'text/html'),
                         body= "\r\n<html><body>Error 501<br>Unsupported Operation</body></html>"))
           }
           #################################################################################
           # Strip any punctuation in this case, other cases may need a specific parsing
           funcname <- gsub('[[:punct:]]','',req$PATH_INFO)

           #################################################################################
           # Requested Function
           reqfunc <- APIoperations[[funcname]]

           #################################################################################
           # Function Parameters
           vars <- names(formals(reqfunc))

           #################################################################################
           # Parse
           qs <- try(httr:::parse_query(gsub("^\\?", "", query)))

           #################################################################################
           # If missing vars return error
           if(!all(names(qs) %in% vars) | !all(vars %in% names(qs))) {
             errorFeed <- 'Missing Variables, or improper Code'
             returnError(errorFeed)
           }

           #################################################################################
           # Return Status 200 and type JSON
           status <- 200L
           headers <- list('Content-Type' = "application/json")


           if (!is.character(query) || identical(query, "")) {
             body <- "\r\n<html><body></body></html>"
           } else {
             body <- jsonlite::toJSON(x = list(result = do.call(reqfunc,lapply(qs,as.numeric))))
           }

           # Print Query String for testing purposes
           print(req$QUERY_STRING)


           ret <- list(status=status,
                       headers=headers,
                       body=body)

           return(ret)

         }

message("Starting server...")

然后我用:

启动服务器
server <- httpuv::startDaemonizedServer(<MYIPADDRESS>, <PORT>, app=app)

然后停止:

httpuv::stopDaemonizedServer(server)

0 个答案:

没有答案