From b0e22960e7738c9b9de0e3ce1b38e14881b252f2 Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Mon, 6 Jan 2025 07:19:37 -0600 Subject: [PATCH] Minor `curl_translate()` polishing/testing (#619) Fixes #500 --- R/curl.R | 4 +++- R/headers.R | 14 +++++--------- tests/testthat/_snaps/curl.md | 11 +++++++++++ tests/testthat/test-curl.R | 14 +++++++++++++- 4 files changed, 32 insertions(+), 11 deletions(-) diff --git a/R/curl.R b/R/curl.R index 6016638d..acd4b946 100644 --- a/R/curl.R +++ b/R/curl.R @@ -56,7 +56,9 @@ curl_translate <- function(cmd, simplify_headers = TRUE) { # Content type set with data type <- data$headers$`Content-Type` - data$headers$`Content-Type` <- NULL + if (!identical(data$data, "")) { + data$headers$`Content-Type` <- NULL + } headers <- curl_simplify_headers(data$headers, simplify_headers) steps <- add_curl_step(steps, "req_headers", dots = headers) diff --git a/R/headers.R b/R/headers.R index 6fdc5dd2..c5c4057a 100644 --- a/R/headers.R +++ b/R/headers.R @@ -1,15 +1,11 @@ as_headers <- function(x, error_call = caller_env()) { if (is.character(x) || is.raw(x)) { - headers <- curl::parse_headers(x) - headers <- headers[grepl(":", headers, fixed = TRUE)] + parsed <- curl::parse_headers(x) + valid <- parsed[grepl(":", parsed, fixed = TRUE)] + halves <- parse_in_half(valid, ":") - equals <- regexpr(":", headers, fixed = TRUE) - pieces <- regmatches(headers, equals, invert = TRUE) - - names <- map_chr(pieces, "[[", 1) - values <- as.list(trimws(map_chr(pieces, "[[", 2))) - - new_headers(set_names(values, names), error_call = error_call) + headers <- set_names(trimws(halves$right), halves$left) + new_headers(as.list(headers), error_call = error_call) } else if (is.list(x)) { new_headers(x, error_call = error_call) } else { diff --git a/tests/testthat/_snaps/curl.md b/tests/testthat/_snaps/curl.md index 5d42dfa3..1c5cface 100644 --- a/tests/testthat/_snaps/curl.md +++ b/tests/testthat/_snaps/curl.md @@ -104,6 +104,17 @@ req_body_raw("abcdef", "text/plain") |> req_perform() +# content type stays in header if no data + + Code + curl_translate("curl http://example.com -H Content-Type:text/plain") + Output + request("http://example.com/") |> + req_headers( + `Content-Type` = "text/plain", + ) |> + req_perform() + # can read from clipboard Code diff --git a/tests/testthat/test-curl.R b/tests/testthat/test-curl.R index 225983a4..de170670 100644 --- a/tests/testthat/test-curl.R +++ b/tests/testthat/test-curl.R @@ -51,7 +51,11 @@ test_that("can handle line breaks", { test_that("headers are parsed", { expect_equal( curl_normalize("curl http://x.com -H 'A: 1'")$headers, - as_headers("A: 1") + new_headers(list(A = "1")) + ) + expect_equal( + curl_normalize("curl http://x.com -H 'B:'")$headers, + new_headers(list(B = "")) ) }) @@ -138,6 +142,14 @@ test_that("can translate data", { }) }) +test_that("content type stays in header if no data", { + skip_if(getRversion() < "4.1") + + expect_snapshot( + curl_translate("curl http://example.com -H Content-Type:text/plain") + ) +}) + test_that("can evaluate simple calls", { request_test() # hack to start server