Skip to content

Commit

Permalink
cleanup http code & fix session_token arg (closes #9)
Browse files Browse the repository at this point in the history
  • Loading branch information
leeper committed Apr 14, 2018
1 parent f8028e2 commit d8b0c7e
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 26 deletions.
60 changes: 39 additions & 21 deletions R/http.r
Expand Up @@ -3,10 +3,12 @@
#' @details This function constructs and signs an SQS API request and returns the results thereof, or relevant debugging information in the case of error.
#' @param url A character string containing an SQS API endpoint URL.
#' @param query An optional named list containing query string parameters and their character values.
#' @param region A character string containing an AWS region. If missing, the default \dQuote{us-east-1} is used.
#' @param key A character string containing an AWS Access Key ID. See \code{\link[aws.signature]{locate_credentials}}.
#' @param secret A character string containing an AWS Secret Access Key. See \code{\link[aws.signature]{locate_credentials}}.
#' @param session_token Optionally, a character string containing an AWS temporary Session Token. See \code{\link[aws.signature]{locate_credentials}}.
#' @param headers A list of headers to pass to the HTTP request.
#' @param verbose A logical indicating whether to be verbose. Default is given by \code{options("verbose")}.
#' @param region A character string specifying an AWS region. See \code{\link[aws.signature]{locate_credentials}}.
#' @param key A character string specifying an AWS Access Key. See \code{\link[aws.signature]{locate_credentials}}.
#' @param secret A character string specifying an AWS Secret Key. See \code{\link[aws.signature]{locate_credentials}}.
#' @param session_token Optionally, a character string specifying an AWS temporary Session Token to use in signing a request. See \code{\link[aws.signature]{locate_credentials}}.
#' @param ... Additional arguments passed to \code{\link[httr]{GET}}.
#' @return If successful, a named list. Otherwise, a data structure of class
#' \dQuote{aws_error} containing any error message(s) from AWS and information
Expand All @@ -17,20 +19,33 @@
#' @importFrom xml2 read_xml as_list
#' @import httr
#' @export
sqsHTTP <- function(url = NULL,
query = list(),
region = Sys.getenv("AWS_DEFAULT_REGION", "us-east-1"),
key = NULL,
secret = NULL,
session_token = NULL,
...) {
sqsHTTP <-
function(
url = NULL,
headers = list(),
query = list(),
verbose = getOption("verbose", FALSE),
region = Sys.getenv("AWS_DEFAULT_REGION", "us-east-1"),
key = NULL,
secret = NULL,
session_token = NULL,
...
) {
# locate and validate credentials
credentials <- locate_credentials(key = key, secret = secret, session_token = session_token, region = region, verbose = verbose)
key <- credentials[["key"]]
secret <- credentials[["secret"]]
session_token <- credentials[["session_token"]]
region <- credentials[["region"]]

# generate request signature
if (is.null(url)) {
url <- paste0("https://sqs.",region,".amazonaws.com")
}
p <- parse_url(url)
action <- if(p$path == "") "/" else paste0("/", p$path)
d_timestamp <- format(Sys.time(), "%Y%m%dT%H%M%SZ", tz = "UTC")
S <- signature_v4_auth(
Sig <- signature_v4_auth(
datetime = d_timestamp,
region = region,
service = "sqs",
Expand All @@ -42,15 +57,18 @@ sqsHTTP <- function(url = NULL,
request_body = "",
key = key,
secret = secret,
session_token = session_token)
headers <- list(`x-amz-date` = d_timestamp,
`x-amz-content-sha256` = S$BodyHash,
Authorization = S$SignatureHeader)
session_token = session_token,
verbose = verbose)
# setup request headers
headers[["x-amz-date"]] <- d_timestamp
headers[["x-amz-content-sha256"]] <- Sig$BodyHash
headers[["Authorization"]] <- Sig[["SignatureHeader"]]
if (!is.null(session_token) && session_token != "") {
headers[["x-amz-security-token"]] <- session_token
}
H <- do.call(add_headers, headers)

# execute request
if (length(query)) {
r <- GET(url, H, query = query, ...)
} else {
Expand All @@ -61,16 +79,16 @@ sqsHTTP <- function(url = NULL,
if (http_error(r)) {
x <- try(as_list(read_xml(cont)), silent = TRUE)
if (inherits(x, "try-error")) {
x <- try(fromJSON(cont)$Error, silent = TRUE)
x <- try(jsonlite::fromJSON(cont)$Error, silent = TRUE)
}
warning(paste0(http_status(r)$message, ": ", x$Code, " (", x$Message, ")"))
h <- headers(r)
out <- structure(x, headers = h, class = "aws_error")
attr(out, "request_canonical") <- S$CanonicalRequest
attr(out, "request_string_to_sign") <- S$StringToSign
attr(out, "request_signature") <- S$SignatureHeader
attr(out, "request_canonical") <- Sig$CanonicalRequest
attr(out, "request_string_to_sign") <- Sig$StringToSign
attr(out, "request_signature") <- Sig$SignatureHeader
} else {
out <- try(fromJSON(cont), silent = TRUE)
out <- try(jsonlite::fromJSON(cont), silent = TRUE)
if (inherits(out, "try-error")) {
out2 <- try(as_list(read_xml(cont)), silent = TRUE)
if (inherits(out2, "try-error")) {
Expand Down
15 changes: 10 additions & 5 deletions man/sqsHTTP.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit d8b0c7e

Please sign in to comment.