-source("./R/custom_classes.R")
+# Copyright (C) The Arvados Authors. All rights reserved.
+#
+# SPDX-License-Identifier: Apache-2.0
-HttpRequest <- setRefClass(
+source("./R/util.R")
- "HttrRequest",
-
- fields = list(
- send_method = "character",
- server_base_url = "character",
- server_relative_url = "character",
- auth_token = "character",
- allowed_methods = "list",
- request_body = "ANY",
- query_filters = "ANY",
- response_limit = "ANY",
- query_offset = "ANY"
- ),
-
- methods = list(
- initialize = function(method,
- token,
- base_url,
- relative_url,
- body = NULL,
- filters = NULL,
- limit = 100,
- offset = 0)
- {
- send_method <<- method
- auth_token <<- token
- server_base_url <<- base_url
- server_relative_url <<- relative_url
- request_body <<- body
- query_filters <<- filters
- response_limit <<- limit
- query_offset <<- offset
- },
+HttpRequest <- R6::R6Class(
- execute = function()
- {
- #Todo(Fudo): Get rid of the switch and make this module more general.
- http_method <- switch(send_method,
- "GET" = .self$getRequest,
- "POST" = .self$postRequest,
- "PUT" = .self$putRequest,
- "DELETE" = .self$deleteRequest,
- "PATCH" = .self$pathcRequest)
- http_method()
- },
+ "HttrRequest",
- getRequest = function()
- {
- requestHeaders <- httr::add_headers(Authorization = .self$getAuthHeader())
- requestQuery <- .self$generateQuery()
- url <- paste0(server_base_url, server_relative_url, requestQuery)
+ public = list(
- server_data <- httr::GET(url = url,
- config = requestHeaders)
- },
+ validContentTypes = NULL,
+ validVerbs = NULL,
- #Todo(Fudo): Try to make this more generic
- postRequest = function()
+ initialize = function()
{
- url <- paste0(server_base_url, server_relative_url)
- requestHeaders <- httr::add_headers("Authorization" = .self$getAuthHeader(),
- "Content-Type" = "application/json")
- response <- POST(url, body = request_body, config = requestHeaders)
+ self$validContentTypes <- c("text", "raw")
+ self$validVerbs <- c("GET", "POST", "PUT", "DELETE", "PROPFIND", "MOVE")
},
- putRequest = function()
+ exec = function(verb, url, headers = NULL, body = NULL, queryParams = NULL,
+ retryTimes = 0)
{
- url <- paste0(server_base_url, server_relative_url)
- requestHeaders <- httr::add_headers("Authorization" = .self$getAuthHeader(),
- "Content-Type" = "application/json")
-
- response <- PUT(url, body = request_body, config = requestHeaders)
- },
+ if(!(verb %in% self$validVerbs))
+ stop("Http verb is not valid.")
- deleteRequest = function()
- {
- url <- paste0(server_base_url, server_relative_url)
- requestHeaders <- httr::add_headers("Authorization" = .self$getAuthHeader(),
- "Content-Type" = "application/json")
- response <- DELETE(url, config = requestHeaders)
- },
+ urlQuery <- self$createQuery(queryParams)
+ url <- paste0(url, urlQuery)
- pathcRequest = function()
- {
- #Todo(Fudo): Implement this later on.
- print("PATCH method")
- },
+ config <- httr::add_headers(unlist(headers))
+ if(toString(Sys.getenv("ARVADOS_API_HOST_INSECURE") == "TRUE"))
+ config$options = list(ssl_verifypeer = FALSE)
- getAuthHeader = function()
- {
- auth_method <- "OAuth2"
- auth_header <- paste(auth_method, auth_token)
+ # times = 1 regular call + numberOfRetries
+ response <- httr::RETRY(verb, url = url, body = body,
+ config = config, times = retryTimes + 1)
},
- generateQuery = function()
+ createQuery = function(queryParams)
{
- #Todo(Fudo): This function is a mess, refactor it
- finalQuery <- "?alt=json"
+ queryParams <- Filter(Negate(is.null), queryParams)
- if(!is.null(query_filters))
+ query <- sapply(queryParams, function(param)
{
- filters <- sapply(query_filters, function(filter)
- {
- if(length(filter) != 3)
- stop("Filter list must have exacthey 3 elements.")
-
- attributeAndOperator = filter[c(1, 2)]
- filterList = filter[[3]]
- filterListIsPrimitive = TRUE
- if(length(filterList) > 1)
- filterListIsPrimitive = FALSE
-
- attributeAndOperator <- sapply(attributeAndOperator, function(component) {
- component <- paste0("\"", component, "\"")
- })
-
- filterList <- sapply(unlist(filterList), function(filter) {
- filter <- paste0("\"", filter, "\"")
- })
-
- filterList <- paste(filterList, collapse = ",+")
-
- if(!filterListIsPrimitive)
- filterList <- paste0("[", filterList, "]")
-
- filter <- c(attributeAndOperator, filterList)
+ if(is.list(param) || length(param) > 1)
+ param <- RListToPythonList(param, ",")
- queryParameter <- paste(filter, collapse = ",+")
- queryParameter <- paste0("[", queryParameter, "]")
-
- })
+ URLencode(as.character(param), reserved = T, repeated = T)
- filters <- paste(filters, collapse = ",+")
- filters <- paste0("[", filters, "]")
+ }, USE.NAMES = TRUE)
- encodedQuery <- URLencode(filters, reserved = T, repeated = T)
-
- finalQuery <- paste0(finalQuery, "&filters=", encodedQuery)
-
- #Todo(Fudo): This is a hack for now. Find a proper solution.
- finalQuery <- stringr::str_replace_all(finalQuery, "%2B", "+")
- }
-
- if(!is.null(response_limit))
+ if(length(query) > 0)
{
- if(!is.numeric(response_limit))
- stop("Limit must be a numeric type.")
-
- finalQuery <- paste0(finalQuery, "&limit=", response_limit)
- }
+ query <- paste0(names(query), "=", query, collapse = "&")
- if(!is.null(query_offset))
- {
- if(!is.numeric(query_offset))
- stop("Offset must be a numeric type.")
-
- finalQuery <- paste0(finalQuery, "&offset=", query_offset)
+ return(paste0("/?", query))
}
- finalQuery
+ return("")
}
- )
+ ),
+
+ cloneable = FALSE
)