page
param
cursor
or token
param
Link:
to next
in response header
nextUrl
in response body
perPage
or pageSize
paramUnfortunately, no standard.
page
, perPage
, cursor
parametershttr2::req_retry()
max_tries
or max_seconds
httr2::req_cache()
= save responses locally if server says its okpath
We’re going to req_retry()
+ req_cache()
a lot, so:
req_perform()
next_req
functionsparam_name
= "page"
or whatever API calls itstart
, offset
= almost always leave as-isresp_pages
= function to convert resp
to page count
max_reqs <- min(max_reqs, total_pages)
resp_complete
= function to check if resp
is last page
\(resp) !length(resp_body_json(resp))
param_name
= "cursor"
or whatever API calls itresp_param_value
= function to convert resp
to next cursor
NULL
if no more pagescrossref_multi <-
crossref_request_cursor |>
req_retry(max_tries = 3) |>
req_perform_iterative(
next_req = iterate_with_cursor(
"cursor",
resp_param_value = \(resp) {
content <- resp_body_json(resp)
if (!length(content$message$items)) {
return(NULL)
}
content$message$`next-cursor`
}
),
max_reqs = Inf
)
length(crossref_multi)
#> [1] 706
rel
= "next"
or whatever API calls itresp_param_value
= function to convert resp
to next cursor
NULL
if no more pagesmtg_cards_single <-
mtg_cards_request |>
req_perform()
resp_header(mtg_cards_single, "link")
#> <https://api.magicthegathering.io/v1/cards?name=bee&page=5&pageSize=20>; rel="last",
#> <https://api.magicthegathering.io/v1/cards?name=bee&page=2&pageSize=20>; rel="next"
mtg_cards_content <- mtg_cards_single |>
resp_body_json()
nextUrl
in response body
free_dictionary_request <-
request("https://api.dictionaryapi.dev/api/v2/entries/en/") |>
req_friendly(cache_name = "free_dictionary")
words <- c("hello", "world", "goodbye")
free_dictionary_reqs <-
purrr::map(words, \(word) req_url_path_append(free_dictionary_request, word))
free_dictionary_reqs |> purrr::map_chr("url")
#> [1] "https://api.dictionaryapi.dev/api/v2/entries/en/hello"
#> [2] "https://api.dictionaryapi.dev/api/v2/entries/en/world"
#> [3] "https://api.dictionaryapi.dev/api/v2/entries/en/goodbye"
httr2::req_perform_parallel()
performs multiple requests simultaneously
req_retry()
(and some other things)req_perform_*()
returns list of responsesresps_data()
takes that list + resp_data
parsing function and mergesresp_body_json
candidates_multi_results <- resps_data(
candidates_multi, fec_resp_parser
)
tibblify::tibblify(candidates_multi_results)
#> # A tibble: 173 × 24
#> active_through candidate_id candidate_inactive candidate_status cycles
#> <int> <chr> <lgl> <chr> <list>
#> 1 2020 P00014241 FALSE N <list [3]>
#> 2 2024 P00008193 FALSE N <list [4]>
#> 3 2020 P00006296 FALSE P <list [4]>
#> 4 2020 P00010900 FALSE N <list [1]>
#> 5 2020 P00012104 FALSE P <list [3]>
#> 6 2020 P40003170 FALSE N <list [5]>
#> 7 2020 P00008128 FALSE N <list [4]>
#> 8 2020 P80004369 FALSE N <list [2]>
#> 9 2020 P00010090 FALSE N <list [3]>
#> 10 2024 P00015297 FALSE N <list [3]>
#> # ℹ 163 more rows
#> # ℹ 19 more variables: district <chr>, district_number <int>,
#> # election_districts <list>, election_years <list>, federal_funds_flag <lgl>,
#> # first_file_date <chr>, has_raised_funds <lgl>,
#> # inactive_election_years <list>, incumbent_challenge <chr>,
#> # incumbent_challenge_full <chr>, last_f2_date <chr>, last_file_date <chr>,
#> # load_date <chr>, name <chr>, office <chr>, office_full <chr>, …
req_perform_iterative
on_error
arg: “stop” or “return”resps_successes()
extracts just successes from resps
listresps_failures()
same, but failuresresps_requests()
to see how they were calledDSLC.io/wapir | Jon Harmon | wapir.io