diff --git a/NEWS.md b/NEWS.md index b92dd80a..22f42946 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,7 +1,8 @@ # httr2 (development version) +* `curl_translate()` now parses the query components of the url (@mgirlich, #259). + * `curl_translate()` now works with multiline commands from the clipboard - (@mgirlich, #254). * New `resp_has_body()` returns a `TRUE` or `FALSE` depending on whether or not the response has a body (#205). diff --git a/R/curl.R b/R/curl.R index b11ab226..47643267 100644 --- a/R/curl.R +++ b/R/curl.R @@ -38,42 +38,37 @@ curl_translate <- function(cmd) { } data <- curl_normalize(cmd) - out <- glue('request("{data$url}")') - add_line <- function(x, y) { - paste0(x, ' %>% \n ', gsub("\n", "\n ", y)) - } + url_pieces <- httr2::url_parse(data$url) + query <- url_pieces$query + url_pieces$query <- NULL + url <- url_build(url_pieces) - if (!is.null(data$method)) { - out <- add_line(out, glue('req_method("{data$method}")')) - } + steps <- glue('request("{url}")') + steps <- add_curl_step(steps, "req_method", main_args = data$method) + + steps <- add_curl_step(steps, "req_url_query", dots = query) # Content type set with data type <- data$headers$`Content-Type` data$headers$`Content-Type` <- NULL - if (length(data$headers) > 0) { - names <- quote_name(names(data$headers)) - values <- encodeString(unlist(data$headers), quote = '"') - args <- paste0(" ", names, " = ", values, ",\n", collapse = "") - - out <- add_line(out, paste0("req_headers(\n", args, ")")) - } + steps <- add_curl_step(steps, "req_headers", dots = data$headers) if (!identical(data$data, "")) { - type <- encodeString(type %||% "application/x-www-form-urlencoded", quote = '"') - body <- encodeString(data$data, quote = '"') - out <- add_line(out, glue("req_body_raw({body}, {type})")) + type <- type %||% "application/x-www-form-urlencoded" + body <- data$data + steps <- add_curl_step(steps, "req_body_raw", main_args = c(body, type)) } - if (!is.null(data$auth)) { - out <- add_line(out, glue('req_auth_basic("{data$auth[[1]]}", "{data$auth[[2]]}")')) - } + steps <- add_curl_step(steps, "req_auth_basic", main_args = unname(data$auth)) + perform_args <- list() if (data$verbose) { - out <- add_line(out, "req_perform(verbosity = 1)") - } else { - out <- add_line(out, "req_perform()") + perform_args$verbosity <- 1 } + steps <- add_curl_step(steps, "req_perform", main_args = perform_args, keep_if_empty = TRUE) + + out <- paste0(steps, collapse = " %>% \n ") out <- paste0(out, "\n") if (clip) { @@ -230,8 +225,42 @@ curl_args <- function(cmd) { # Helpers ----------------------------------------------------------------- is_syntactic <- function(x) { - x == make.names(x) + x == "" | x == make.names(x) } quote_name <- function(x) { ifelse(is_syntactic(x), x, encodeString(x, quote = "`")) } + +add_curl_step <- function(steps, + f, + ..., + main_args = NULL, + dots = NULL, + keep_if_empty = FALSE) { + check_dots_empty0(...) + args <- c(main_args, dots) + + if (is_empty(args) && !keep_if_empty) { + return(steps) + } + + names <- quote_name(names2(args)) + string <- vapply(args, is.character, logical(1L)) + values <- unlist(args) + values <- ifelse(string, encodeString(values, quote = '"'), values) + + args_named <- ifelse( + names == "", + paste0(values), + paste0(names, " = ", values) + ) + if (is_empty(dots)) { + args_string <- paste0(args_named, collapse = ", ") + new_step <- paste0(f, "(", args_string, ")") + } else { + args_string <- paste0(" ", args_named, ",\n", collapse = "") + new_step <- paste0(f, "(\n", args_string, " )") + } + + c(steps, new_step) +} diff --git a/tests/testthat/_snaps/curl.md b/tests/testthat/_snaps/curl.md index 980104dc..bd0139bc 100644 --- a/tests/testthat/_snaps/curl.md +++ b/tests/testthat/_snaps/curl.md @@ -47,6 +47,18 @@ request("http://x.com") %>% req_perform(verbosity = 1) +# can translate query + + Code + curl_translate("curl http://x.com?string=abcde&b=2") + Output + request("http://x.com") %>% + req_url_query( + string = "abcde", + b = "2", + ) %>% + req_perform() + # can translate data Code diff --git a/tests/testthat/test-curl.R b/tests/testthat/test-curl.R index 4d94c173..8789b842 100644 --- a/tests/testthat/test-curl.R +++ b/tests/testthat/test-curl.R @@ -96,6 +96,12 @@ test_that("can translate to httr calls", { }) }) +test_that("can translate query", { + expect_snapshot({ + curl_translate("curl http://x.com?string=abcde&b=2") + }) +}) + test_that("can translate data", { expect_snapshot({ curl_translate("curl http://example.com --data abcdef")