Skip to content

Commit

Permalink
Implement user agent functionality (#34)
Browse files Browse the repository at this point in the history
* RStudio now gives project IDs.

* Better user agent management.

Better file organization.

Closes #29.
  • Loading branch information
jonthegeek authored Dec 23, 2024
1 parent cf92bd8 commit c086015
Show file tree
Hide file tree
Showing 65 changed files with 1,369 additions and 656 deletions.
6 changes: 5 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Up @@ -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)
Expand All @@ -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
Expand Up @@ -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

Expand Down
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
Expand Up @@ -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

0 comments on commit c086015

Please sign in to comment.