Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement user agent functionality #34

Merged
merged 2 commits into from
Dec 23, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -20,16 +20,20 @@ Imports:
glue,
httr2 (>= 1.0.0),
jsonlite,
lifecycle,
purrr,
rlang,
stbl,
stringr,
utils,
vctrs
Suggests:
covr,
stringi,
testthat (>= 3.0.0)
Remotes:
jonthegeek/stbl
Config/testthat/edition: 3
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.3.1
RoxygenNote: 7.3.2
4 changes: 3 additions & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
@@ -9,10 +9,11 @@ export(call_api)
export(compact_nested_list)
export(do_if_fn_defined)
export(req_auth_api_key)
export(req_init)
export(req_modify)
export(req_perform_opinionated)
export(req_pkg_user_agent)
export(req_prepare)
export(req_setup)
export(resp_parse)
export(stabilize_string)
export(url_normalize)
@@ -21,4 +22,5 @@ importFrom(cli,cli_abort)
importFrom(fs,path)
importFrom(httr2,req_perform)
importFrom(httr2,req_perform_iterative)
importFrom(lifecycle,deprecated)
importFrom(rlang,":=")
63 changes: 60 additions & 3 deletions R/aaa-shared.R
Original file line number Diff line number Diff line change
@@ -2,10 +2,67 @@
#'
#' Reused parameter definitions are gathered here for easier editing.
#'
#' @param req A [httr2::request()] object.
#' @param x The object to update.
#' @param additional_user_agent (`length-1 character`) A string to identify
#' where a request is coming from. We automatically include information about
#' your package and nectar, but use this to provide additional details.
#' Default `NULL`.
#' @param api_key (`length-1 character`) The API key to use.
#' @param arg (`length-1 character`) An argument name as a string. This argument
#' will be mentioned in error messages as the input that is at the origin of a
#' problem.
#' @param auth_args (`list`) An optional list of arguments to the `auth_fn`
#' function.
#' @param auth_fn (`function`) A function to use to authenticate the request. By
#' default (`NULL`), no authentication is performed.
#' @param base_url (`length-1 character`) The part of the url that is shared by
#' all calls to the API. In some cases there may be a family of base URLs,
#' from which you will need to choose one.
#' @param body (multiple types) An object to use as the body of the request. If
#' any component of the body is a path, pass it through [fs::path()] or
#' otherwise give it the class "fs_path" to indicate that it is a path.
#' @param call (`environment`) The environment from which a function was
#' called, e.g. [rlang::caller_env()] (the default). The environment will be
#' mentioned in error messages as the source of the error. This argument is
#' particularly useful for functions that are intended to be called as
#' utilities inside other functions.
#' @param existing_user_agent (`length-1 character`, optional) An existing user
#' agent, such as the value of `req$options$useragent` in a [httr2::request()]
#' object.
#' @param method (`length-1 character`, optional) If the method is something
#' other than `GET` or `POST`, supply it. Case is ignored.
#' @param mime_type (`length-1 character`) The mime type of any files present in
#' the body. Some APIs allow you to leave this as NULL for them to guess.
#' @param name (`length-1 character`) The name of a package or other thing to
#' add to or remove from the user agent string.
#' @param pkg_name (`length-1 character`) The name of the calling package. This
#' will usually be automatically determined based on the source of the call.
#' @param pkg_url (`length-1 character`) A url for information about the calling
#' package (default `NULL`).
#' @param parameter_name (`length-1 character`) The name to use for the API key.
#' @param path (`character` or `list`) The route to an API endpoint. Optionally,
#' a list or character vector with the path as one or more unnamed arguments
#' (which will be concatenated with "/") plus named arguments to
#' [glue::glue()] into the path.
#' @param query (`character` or `list`) An optional list or character vector of
#' parameters to pass in the query portion of the request. Can also include a
#' `.multi` argument to pass to [httr2::req_url_query()] to control how
#' elements containing multiple values are handled.
#' @param req (`httr2_request`) A [httr2::request()] object.
#' @param resp (`httr2_response` or `list`) A single [httr2::response()] object
#' (as returned by [httr2::req_perform()]) or a list of such objects (as
#' returned by [httr2::req_perform_iterative()]).
#' @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()].
#' @param response_parser_args (`list`) An optional list of arguments to pass to
#' the `response_parser` function (in addition to `resp`).
#' @param url (`length-1 character`) An optional url associated with `name`.
#' @param version (`length-1 character`) The version of `name`.
#' @param x (multiple types) The object to update.
#' @param ... These dots are for future extensions and must be empty.
#'
#' @name .shared-parameters
#' @name .shared-params
#' @keywords internal
NULL

64 changes: 0 additions & 64 deletions R/call.R

This file was deleted.

62 changes: 62 additions & 0 deletions R/call_api.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#' Send a request to an API
#'
#' @description `r lifecycle::badge("questioning")`
#'
#' This function implements an opinionated framework for making API calls. It
#' is intended to be used inside an API client package. It serves as a wrapper
#' around the `req_` family of functions, such as [httr2::request()], as well
#' as [httr2::req_perform()] and [httr2::req_perform_iterative()], and, by
#' default, [httr2::resp_body_json()].
#'
#' @seealso [req_prepare()], [req_perform_opinionated()], and [resp_parse()] for
#' finer control of the process.
#'
#' @inheritParams rlang::args_dots_empty
#' @inheritParams req_prepare
#' @inheritParams req_perform_opinionated
#' @inheritParams resp_parse
#' @param response_parser_args (`list`) Additional arguments to pass to the
#' `response_parser`.
#'
#' @return The response from the API, parsed by the `response_parser`.
#' @export
call_api <- function(base_url,
...,
path = NULL,
query = NULL,
body = NULL,
mime_type = NULL,
method = NULL,
auth_fn = NULL,
auth_args = list(),
response_parser = httr2::resp_body_json,
response_parser_args = list(),
next_req = NULL,
max_reqs = Inf,
max_tries_per_req = 3,
additional_user_agent = NULL) {
rlang::check_dots_empty()
req <- req_prepare(
base_url,
path = path,
query = query,
body = body,
mime_type = mime_type,
method = method,
additional_user_agent = additional_user_agent,
auth_fn = auth_fn,
auth_args = auth_args
)
resp <- req_perform_opinionated(
req,
next_req = next_req,
max_reqs = max_reqs,
max_tries_per_req = max_tries_per_req
)
resp <- resp_parse(
resp,
response_parser = response_parser,
!!!response_parser_args
)
return(resp)
}
1 change: 1 addition & 0 deletions R/nectar-package.R
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@
#' @importFrom fs path
#' @importFrom httr2 req_perform
#' @importFrom httr2 req_perform_iterative
#' @importFrom lifecycle deprecated
#' @importFrom rlang :=
## usethis namespace: end
NULL
101 changes: 0 additions & 101 deletions R/req.R

This file was deleted.

Loading