R/http-curl.R

Defines functions httpCurl

# HTTP transport using the curl command-line utility. Useful on systems that have a working curl but
# not necessarily a working curl library, such as Windows 10.

httpCurl <- function(
  protocol,
  host,
  port,
  method,
  path,
  headers,
  contentType = NULL,
  contentFile = NULL,
  certificate = NULL,
  timeout = NULL
) {
  if (!is.null(contentFile) && is.null(contentType)) {
    stop("You must specify a contentType for the specified file")
  }

  if (!is.null(contentFile)) {
    fileLength <- file.info(contentFile)$size
  }

  headers <- appendCookieHeaders(
    list(protocol = protocol, host = host, port = port, path = path),
    headers
  )
  extraHeaders <- character()
  for (header in names(headers)) {
    if (
      !identical(header, "Content-Type") && !identical(header, "Content-Length")
    ) {
      extraHeaders <- paste(extraHeaders, "--header")
      extraHeaders <- paste(
        extraHeaders,
        paste('"', header, ": ", headers[[header]], '"', sep = "")
      )
    }
  }

  outputFile <- tempfile()

  command <- paste("curl", "-i", "-X", method)

  if (httpVerbose()) {
    command <- paste(command, "-v")
  }

  if (!is.null(timeout)) {
    command <- paste(command, "--connect-timeout", timeout)
  }

  if (!is.null(contentFile)) {
    command <- paste(
      command,
      "-T",
      shQuote(contentFile),
      "--header",
      paste('"', "Content-Type: ", contentType, '"', sep = ""),
      "--header",
      paste('"', "Content-Length: ", fileLength, '"', sep = "")
    )
  }

  # add prefix to port if necessary
  if (nzchar(port)) {
    port <- paste(":", port, sep = "")
  }

  if (!isTRUE(getOption("rsconnect.check.certificate", TRUE))) {
    # suppressed certificate check
    command <- paste(command, "--insecure")
  } else if (!is.null(certificate)) {
    # cert check not suppressed and we have a supplied cert
    command <- paste(command, "--cacert", shQuote(certificate))
  }

  command <- paste(
    command,
    extraHeaders,
    "--header",
    "Expect:",
    "--user-agent",
    userAgent(),
    "--silent",
    "--show-error",
    "-o",
    shQuote(outputFile),
    paste('"', protocol, "://", host, port, path, '"', sep = "")
  )

  result <- NULL
  time <- system.time(gcFirst = FALSE, {
    result <- system(command)
  })
  httpTrace(method, path, time)

  # emit JSON trace if requested
  if (
    !is.null(contentFile) &&
      httpTraceJson() &&
      identical(contentType, "application/json")
  ) {
    fileLength <- file.info(contentFile)$size
    fileContents <- readBin(contentFile, what = "raw", n = fileLength)
    cat(paste0("<< ", rawToChar(fileContents), "\n"))
  }

  if (result == 0) {
    fileConn <- file(outputFile, "rb")
    defer(close(fileConn))
    readHttpResponse(
      list(
        protocol = protocol,
        host = host,
        port = port,
        method = method,
        path = path
      ),
      fileConn
    )
  } else {
    stop(paste("Curl request failed (curl error", result, "occurred)"))
  }
}

Try the rsconnect package in your browser

Any scripts or data that you put into this service are public.

rsconnect documentation built on June 26, 2025, 5:07 p.m.