diff --git a/R/aaa-shared_params.R b/R/aaa-shared_params.R index 7e00694..f8f16ce 100644 --- a/R/aaa-shared_params.R +++ b/R/aaa-shared_params.R @@ -71,9 +71,9 @@ #' @param resp_body_fn (`function`) A function to extract the body of the #' response. Default: [resp_body_auto()]. #' @param response_parser (`function`) A function to parse the server response -#' (`resp`). Defaults to [httr2::resp_body_json()], since JSON responses are -#' common. Set this to `NULL` to return the raw response from -#' [httr2::req_perform()]. +#' (`resp`). Defaults to [resp_tidy()], which applies a tidying policy from +#' the request when available and otherwise uses [resp_body_auto()]. Set this +#' to `NULL` to return the raw response from [httr2::req_perform()]. #' @param response_parser_args (`list`) An optional list of arguments to pass to #' the `response_parser` function (in addition to `resp`). #' @param spec (`tspec` or `NULL`) A specification used by diff --git a/R/resp_parse.R b/R/resp_parse.R index cb0c799..838c315 100644 --- a/R/resp_parse.R +++ b/R/resp_parse.R @@ -84,7 +84,10 @@ resp_parse.list <- function(resps, ..., response_parser = resp_tidy) { } .resps_combine <- function(resps_parsed) { - purrr::discard(resps_parsed, is.null) + resps_parsed <- purrr::discard(resps_parsed, is.null) + if (!length(resps_parsed)) { + return(NULL) + } if (inherits(resps_parsed[[1]], "raw")) { # This is tested, but covr doesn't believe it. return(resps_parsed) # nocov diff --git a/man/dot-shared-params.Rd b/man/dot-shared-params.Rd index d2f75cf..c709c06 100644 --- a/man/dot-shared-params.Rd +++ b/man/dot-shared-params.Rd @@ -96,9 +96,9 @@ list of such objects (as returned by \code{\link[=req_perform_opinionated]{req_p response. Default: \code{\link[=resp_body_auto]{resp_body_auto()}}.} \item{response_parser}{(\code{function}) A function to parse the server response -(\code{resp}). Defaults to \code{\link[httr2:resp_body_json]{httr2::resp_body_json()}}, since JSON responses are -common. Set this to \code{NULL} to return the raw response from -\code{\link[httr2:req_perform]{httr2::req_perform()}}.} +(\code{resp}). Defaults to \code{\link[=resp_tidy]{resp_tidy()}}, which applies a tidying policy from +the request when available and otherwise uses \code{\link[=resp_body_auto]{resp_body_auto()}}. Set this +to \code{NULL} to return the raw response from \code{\link[httr2:req_perform]{httr2::req_perform()}}.} \item{response_parser_args}{(\code{list}) An optional list of arguments to pass to the \code{response_parser} function (in addition to \code{resp}).} diff --git a/man/resp_parse.Rd b/man/resp_parse.Rd index 5c54674..4a087a6 100644 --- a/man/resp_parse.Rd +++ b/man/resp_parse.Rd @@ -37,9 +37,9 @@ useful for functions that are intended to be called as utilities inside other functions.} \item{response_parser}{(\code{function}) A function to parse the server response -(\code{resp}). Defaults to \code{\link[httr2:resp_body_json]{httr2::resp_body_json()}}, since JSON responses are -common. Set this to \code{NULL} to return the raw response from -\code{\link[httr2:req_perform]{httr2::req_perform()}}.} +(\code{resp}). Defaults to \code{\link[=resp_tidy]{resp_tidy()}}, which applies a tidying policy from +the request when available and otherwise uses \code{\link[=resp_body_auto]{resp_body_auto()}}. Set this +to \code{NULL} to return the raw response from \code{\link[httr2:req_perform]{httr2::req_perform()}}.} } \value{ The response parsed by the \code{response_parser}. If \code{resps} was a list, diff --git a/tests/testthat/test-resp_parse.R b/tests/testthat/test-resp_parse.R index 79ac23d..9bcdbbf 100644 --- a/tests/testthat/test-resp_parse.R +++ b/tests/testthat/test-resp_parse.R @@ -61,6 +61,39 @@ test_that("resp_parse parses lists of httr2_responses (#10)", { expect_identical(test_result, 1:6) }) +test_that("resp_parse drops NULL parsed pages before combining (#90)", { + resps <- list( + httr2::response_json(body = 1:2), + httr2::response_json(body = list()), + httr2::response_json(body = 3:4) + ) + parser <- function(resp) { + body <- httr2::resp_body_json(resp) + if (!length(body)) { + return(NULL) + } + body + } + test_result <- resp_parse(resps, response_parser = parser) + expect_identical(test_result, as.list(1:4)) +}) + +test_that("resp_parse returns NULL when all parsed pages are NULL (#90)", { + resps <- list( + httr2::response_json(body = list()), + httr2::response_json(body = list()) + ) + parser <- function(resp) { + body <- httr2::resp_body_json(resp) + if (!length(body)) { + return(NULL) + } + body + } + test_result <- resp_parse(resps, response_parser = parser) + expect_null(test_result) +}) + test_that("resp_parse works for raw results (#11)", { # reqs <- list( # httr2::request("https://httr2.r-lib.org/logo.png"), diff --git a/vignettes/nectar.Rmd b/vignettes/nectar.Rmd index 27fb9d1..e13156b 100644 --- a/vignettes/nectar.Rmd +++ b/vignettes/nectar.Rmd @@ -26,6 +26,14 @@ The main entry point in nectar is `req_prepare()`. It wraps `httr2::request()` a Here we prepare a request to the Crossref `/works` endpoint. We ask for ten results per page (`rows = 10`), select only the "publisher" and "DOI" fields, tell `{httr2}` to concatenate the `select` parameter with commas (`.multi`), and set the `cursor` parameter to `"*"` to trigger cursor-based pagination: +```{r prepare, eval = FALSE} +req <- req_prepare( + "https://api.crossref.org/works", + query = list( + rows = 10, cursor = "*", select = c("publisher", "DOI"), .multi = "comma" + ) +) +``` ## Authentication with `auth_api_key()`