From 3f34eb83c451da1ca2dda1c674e3c2a5338bc1b1 Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Mon, 23 Dec 2024 11:09:10 -0600 Subject: [PATCH 1/3] Implement `req_headers_redacted()` Which I think is a friendlier interface than the `.redact` argument to `req_headers()`. Fixes #561 --- NEWS.md | 1 + R/req-headers.R | 17 +++++++++++++++-- tests/testthat/test-req-headers.R | 2 ++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index f09f990e..e717f2c2 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,6 @@ # httr2 (development version) +* New `req_headers_redacted()` provides a user-friendlier way to set redacted headers (#561). * `url_parse()` now uses `curl::curl_parse_url()` which is much faster and more correct (#577). * `req_retry()` now defaults to `max_tries = 2` with a message. Set to `max_tries = 1` to disable retries. diff --git a/R/req-headers.R b/R/req-headers.R index e9435873..7e0998d6 100644 --- a/R/req-headers.R +++ b/R/req-headers.R @@ -1,6 +1,9 @@ #' Modify request headers #' -#' `req_headers()` allows you to set the value of any header. +#' `req_headers()` allows you to set the value of any header. Use +#' `req_headers_redacted()` to add "redacted" headers which httr2 strives +#' to avoid printing to the console. This is good practice for headers used +#' for authentication to avoid accidentally including them in log files. #' #' @param .req A [request]. #' @param ... <[`dynamic-dots`][rlang::dyn-dots]> Name-value pairs of headers @@ -51,7 +54,8 @@ #' #' # Use `.redact` to hide a header in the output #' req |> -#' req_headers(Secret = "this-is-private", Public = "but-this-is-not", .redact = "Secret") |> +#' req_headers_redacted(Secret = "this-is-private") |> +#' req_headers(Public = "but-this-is-not") |> #' req_dry_run() req_headers <- function(.req, ..., .redact = NULL) { check_request(.req) @@ -68,3 +72,12 @@ req_headers <- function(.req, ..., .redact = NULL) { .req } + +#' @export +#' @rdname req_headers +req_headers_redacted <- function(.req, ...) { + check_request(.req) + + dots <- list(...) + req_headers(.req, !!!dots, .redact = names(dots)) +} diff --git a/tests/testthat/test-req-headers.R b/tests/testthat/test-req-headers.R index 036a6790..1b7f3883 100644 --- a/tests/testthat/test-req-headers.R +++ b/tests/testthat/test-req-headers.R @@ -30,6 +30,8 @@ test_that("can control which headers to redact", { expect_redact(req_headers(req, a = 1L, b = 2L, .redact = c("a", "b")), c("a", "b")) expect_redact(req_headers(req, a = 1L, b = 2L, .redact = "a"), "a") + expect_redact(req_headers_redacted(req, a = 1L, b = 2L), c("a", "b")) + expect_snapshot(error = TRUE, { req_headers(req, a = 1L, b = 2L, .redact = 1L) }) From 3cbe0107efdba60698487043a77aa2c0af6c255f Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Mon, 23 Dec 2024 13:24:49 -0600 Subject: [PATCH 2/3] Re-document --- NAMESPACE | 1 + man/req_headers.Rd | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 0613c62a..7f9a4075 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -67,6 +67,7 @@ export(req_cookies_set) export(req_dry_run) export(req_error) export(req_headers) +export(req_headers_redacted) export(req_method) export(req_oauth) export(req_oauth_auth_code) diff --git a/man/req_headers.Rd b/man/req_headers.Rd index c16d6932..141de9f6 100644 --- a/man/req_headers.Rd +++ b/man/req_headers.Rd @@ -2,9 +2,12 @@ % Please edit documentation in R/req-headers.R \name{req_headers} \alias{req_headers} +\alias{req_headers_redacted} \title{Modify request headers} \usage{ req_headers(.req, ..., .redact = NULL) + +req_headers_redacted(.req, ...) } \arguments{ \item{.req}{A \link{request}.} @@ -24,7 +27,10 @@ are not redacted.} A modified HTTP \link{request}. } \description{ -\code{req_headers()} allows you to set the value of any header. +\code{req_headers()} allows you to set the value of any header. Use +\code{req_headers_redacted()} to add "redacted" headers which httr2 strives +to avoid printing to the console. This is good practice for headers used +for authentication to avoid accidentally including them in log files. } \examples{ req <- request("http://example.com") @@ -64,6 +70,7 @@ req |> # Use `.redact` to hide a header in the output req |> - req_headers(Secret = "this-is-private", Public = "but-this-is-not", .redact = "Secret") |> + req_headers_redacted(Secret = "this-is-private") |> + req_headers(Public = "but-this-is-not") |> req_dry_run() } From 3ce18e13a53e4fdf20a9c63daa521cc2d846a800 Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Mon, 6 Jan 2025 07:25:18 -0600 Subject: [PATCH 3/3] Tweak docs --- R/req-headers.R | 24 ++++++++++++++---------- man/req_headers.Rd | 23 +++++++++++++---------- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/R/req-headers.R b/R/req-headers.R index 7e0998d6..3d099cc8 100644 --- a/R/req-headers.R +++ b/R/req-headers.R @@ -1,9 +1,11 @@ #' Modify request headers #' -#' `req_headers()` allows you to set the value of any header. Use -#' `req_headers_redacted()` to add "redacted" headers which httr2 strives -#' to avoid printing to the console. This is good practice for headers used -#' for authentication to avoid accidentally including them in log files. +#' @description +#' `req_headers()` allows you to set the value of any header. +#' +#' `req_headers_redacted()` is a variation that adds "redacted" headers, which +#' httr2 avoids printing on the console. This is good practice for +#' authentication headers to avoid accidentally leaking them in log files. #' #' @param .req A [request]. #' @param ... <[`dynamic-dots`][rlang::dyn-dots]> Name-value pairs of headers @@ -49,14 +51,16 @@ #' # If you have headers in a list, use !!! #' headers <- list(HeaderOne = "one", HeaderTwo = "two") #' req |> -#' req_headers(!!!headers, HeaderThree = "three") |> -#' req_dry_run() +#' req_headers(!!!headers, HeaderThree = "three") |> +#' req_dry_run() #' -#' # Use `.redact` to hide a header in the output -#' req |> +#' # Use `req_headers_redacted()`` to hide a header in the output +#' req_secret <- req |> #' req_headers_redacted(Secret = "this-is-private") |> -#' req_headers(Public = "but-this-is-not") |> -#' req_dry_run() +#' req_headers(Public = "but-this-is-not") +#' +#' req_secret +#' req_secret |> req_dry_run() req_headers <- function(.req, ..., .redact = NULL) { check_request(.req) diff --git a/man/req_headers.Rd b/man/req_headers.Rd index 141de9f6..c78d5cdb 100644 --- a/man/req_headers.Rd +++ b/man/req_headers.Rd @@ -27,10 +27,11 @@ are not redacted.} A modified HTTP \link{request}. } \description{ -\code{req_headers()} allows you to set the value of any header. Use -\code{req_headers_redacted()} to add "redacted" headers which httr2 strives -to avoid printing to the console. This is good practice for headers used -for authentication to avoid accidentally including them in log files. +\code{req_headers()} allows you to set the value of any header. + +\code{req_headers_redacted()} is a variation that adds "redacted" headers, which +httr2 avoids printing on the console. This is good practice for +authentication headers to avoid accidentally leaking them in log files. } \examples{ req <- request("http://example.com") @@ -65,12 +66,14 @@ req |> # If you have headers in a list, use !!! headers <- list(HeaderOne = "one", HeaderTwo = "two") req |> - req_headers(!!!headers, HeaderThree = "three") |> - req_dry_run() + req_headers(!!!headers, HeaderThree = "three") |> + req_dry_run() -# Use `.redact` to hide a header in the output -req |> +# Use `req_headers_redacted()`` to hide a header in the output +req_secret <- req |> req_headers_redacted(Secret = "this-is-private") |> - req_headers(Public = "but-this-is-not") |> - req_dry_run() + req_headers(Public = "but-this-is-not") + +req_secret +req_secret |> req_dry_run() }