| Title: | Utilities for Working with Google APIs |
| Version: | 1.7.0 |
| Description: | Provides utilities for working with Google APIs https://developers.google.com/apis-explorer. This includes functions and classes for handling common credential types and for preparing, executing, and processing HTTP requests. |
| License: | MIT + file LICENSE |
| URL: | https://gargle.r-lib.org, https://github.com/r-lib/gargle |
| BugReports: | https://github.com/r-lib/gargle/issues |
| Depends: | R (≥ 4.2) |
| Imports: | cli (≥ 3.0.1), fs (≥ 1.3.1), glue (≥ 1.3.0), httr (≥ 1.4.5), jsonlite, lifecycle, openssl, R6, rappdirs, rlang (≥ 1.1.0), stats, utils, withr |
| Suggests: | aws.ec2metadata, aws.signature, covr, httpuv, knitr, rmarkdown, spelling, testthat (≥ 3.1.7) |
| VignetteBuilder: | knitr |
| Config/Needs/website: | tidyverse/tidytemplate |
| Config/roxygen2/version: | 8.1.0 |
| Config/testthat/edition: | 3 |
| Config/usethis/last-upkeep: | 2026-10-20 |
| Encoding: | UTF-8 |
| Language: | en-US |
| NeedsCompilation: | no |
| Packaged: | 2026-10-28 16:32:41 UTC; jenny |
| Author: | Jennifer Bryan |
| Maintainer: | Jennifer Bryan <jenny@posit.co> |
| Repository: | CRAN |
| Date/Publication: | 2026-10-28 19:50:02 UTC |
gargle: Utilities for Working with Google APIs
Description
Provides utilities for working with Google APIs https://developers.google.com/apis-explorer. This includes functions and classes for handling common credential types and for preparing, executing, and processing HTTP requests.
Author(s)
Maintainer: Jennifer Bryan jenny@posit.co (ORCID)
Authors:
Jennifer Bryan jenny@posit.co (ORCID)
Craig Citro craigcitro@google.com
Hadley Wickham hadley@posit.co (ORCID)
Other contributors:
Google Inc [copyright holder]
Posit Software, PBC (ROR) [copyright holder, funder]
See Also
Useful links:
Report bugs at https://github.com/r-lib/gargle/issues
Authorization state
Description
An AuthState object manages an authorization state, typically on behalf of
a wrapper package that makes requests to a Google API.
The vignette("gargle-auth-in-client-package") describes a design for wrapper
packages that relies on an AuthState object. This state can then be
incorporated into the package's requests for tokens and can control the
inclusion of tokens in requests to the target API.
-
api_keyis the simplest way to associate a request with a specific Google Cloud Platform project. A few calls to certain APIs, e.g. reading a public Sheet, can succeed with an API key, but this is the exception. -
clientis an OAuth client ID (and secret) associated with a specific Google Cloud Platform project. This is used in the OAuth flow, in which an authenticated user authorizes the client to access or manipulate data on their behalf. -
auth_activereflects whether outgoing requests will be authorized by an authenticated user or are unauthorized requests for public resources. These two states correspond to sending a request with a token versus an API key, respectively. -
credis where the current token is cached within a session, once one has been fetched. It is generally assumed to be an instance ofhttr::TokenServiceAccountorhttr::Token2.0(or a subclass thereof), probably obtained viatoken_fetch()(or one of its constituent credential fetching functions).
An AuthState should be created through the constructor function
init_AuthState(), which has more details on the arguments.
Public fields
Methods
Public methods
AuthState$new()
Create a new AuthState
Usage
AuthState$new( package = NA_character_, client = NULL, api_key = NULL, auth_active = TRUE, cred = NULL, app = deprecated() )
Arguments
Details
For more details on the parameters, see init_AuthState()
AuthState$format()
Format an AuthState
Usage
AuthState$format(...)
Arguments
...Not used.
AuthState$set_client()
Set the OAuth client
Usage
AuthState$set_client(client)
Arguments
clientAn OAuth client.
AuthState$set_app()
Deprecated method to set
the OAuth client
Usage
AuthState$set_app(app)
Arguments
AuthState$set_api_key()
Set the API key
Usage
AuthState$set_api_key(value)
Arguments
valueAn API key.
AuthState$set_auth_active()
Set whether auth is (in)active
Usage
AuthState$set_auth_active(value)
Arguments
valueLogical, indicating whether to send requests authorized with user credentials.
AuthState$set_cred()
Set credentials
Usage
AuthState$set_cred(cred)
Arguments
credUser credentials.
AuthState$clear_cred()
Clear credentials
Usage
AuthState$clear_cred()
AuthState$get_cred()
Get credentials
Usage
AuthState$get_cred()
AuthState$has_cred()
Report if we have credentials
Usage
AuthState$has_cred()
AuthState$clone()
The objects of this class are cloneable with this method.
Usage
AuthState$clone(deep = FALSE)
Arguments
deepWhether to make a deep clone.
OAuth2 token objects specific to Google APIs
Description
Gargle2.0 is based on the Token2.0 class provided in
httr. The preferred way to create a Gargle2.0 token is through the
constructor function gargle2.0_token(). Key differences with Token2.0:
The key for a cached
Token2.0comes from hashing the endpoint, client, and scopes. For theGargle2.0subclass, the identifier or key is expanded to include the email address associated with the token. This makes it easier to work with Google APIs with multiple identities.-
Gargle2.0tokens are cached, by default, at the user level, following the XDG spec for storing user-specific data and cache files. In contrast, the default location forToken2.0is./.httr-oauth, i.e. in current working directory.Gargle2.0behaviour makes it easier to reuse tokens across projects and makes it less likely that tokens are accidentally synced to a remote location like GitHub or DropBox. Each
Gargle2.0token is cached in its own file. The token cache is a directory of such files. In contrast,Token2.0tokens are cached as components of a list, which is typically serialized to./.httr-oauth.
Super classes
httr::Token -> httr::Token2.0 -> Gargle2.0
Public fields
emailEmail associated with the token.
packageName of the package requesting a token. Used in messages.
clientAn OAuth client.
Methods
Public methods
Inherited methods
Gargle2.0$new()
Create a Gargle2.0 token
Usage
Gargle2.0$new( email = gargle_oauth_email(), client = gargle_client(), package = "gargle", credentials = NULL, params = list(), cache_path = gargle_oauth_cache(), app = deprecated() )
Arguments
emailOptional email address. See
gargle2.0_token()for full details.clientAn OAuth consumer application.
packageName of the package requesting a token. Used in messages.
credentialsExists largely for testing purposes.
paramsA list of parameters for the internal function
init_oauth2.0(), which is a modified version ofhttr::init_oauth2.0(). gargle actively usesscopeanduse_oob, but does not useuser_params,type,as_header(hard-wired toTRUE),use_basic_auth(accept default ofuse_basic_auth = FALSE),config_init, orclient_credentials.cache_pathSpecifies the OAuth token cache. Read more in
gargle_oauth_cache().app
Returns
A Gargle2.0 token.
Gargle2.0$format()
Format a Gargle2.0 token
Usage
Gargle2.0$format(...)
Arguments
...Not used.
Gargle2.0$print()
Print a Gargle2.0 token
Usage
Gargle2.0$print(...)
Arguments
...Not used.
Gargle2.0$hash()
Generate the email-augmented hash of a Gargle2.0 token
Usage
Gargle2.0$hash()
Gargle2.0$cache()
Put a Gargle2.0 token into the cache
Usage
Gargle2.0$cache()
Gargle2.0$load_from_cache()
(Attempt to) get a Gargle2.0 token from the cache
Usage
Gargle2.0$load_from_cache()
Gargle2.0$refresh()
(Attempt to) refresh a Gargle2.0 token
Usage
Gargle2.0$refresh()
Gargle2.0$init_credentials()
Initiate a new Gargle2.0 token
Usage
Gargle2.0$init_credentials()
Gargle2.0$clone()
The objects of this class are cloneable with this method.
Usage
Gargle2.0$clone(deep = FALSE)
Arguments
deepWhether to make a deep clone.
Token for use on Google Compute Engine instances
Description
This class uses the metadata service available on GCE VMs to fetch access
tokens. Not intended for direct use. See credentials_gce() instead.
Super classes
httr::Token -> httr::Token2.0 -> GceToken
Methods
Public methods
Inherited methods
GceToken$new()
Get an access for a GCE service account.
Usage
GceToken$new(params)
Arguments
paramsA list of parameters for
fetch_gce_access_token().
Returns
A GceToken.
GceToken$init_credentials()
Request an access token.
Usage
GceToken$init_credentials()
GceToken$refresh()
Refreshes the token. In this case, that just means "ask again for an access token".
Usage
GceToken$refresh()
GceToken$can_refresh()
Placeholder implementation of required method. Returns TRUE.
Usage
GceToken$can_refresh()
GceToken$format()
Format a GceToken().
Usage
GceToken$format(...)
Arguments
...Not used.
GceToken$print()
Print a GceToken().
Usage
GceToken$print(...)
Arguments
...Not used.
GceToken$cache()
Placeholder implementation of required method.
Usage
GceToken$cache()
GceToken$load_from_cache()
Placeholder implementation of required method.
Usage
GceToken$load_from_cache()
GceToken$revoke()
Placeholder implementation of required method.
Usage
GceToken$revoke()
GceToken$validate()
Placeholder implementation of required method
Usage
GceToken$validate()
GceToken$clone()
The objects of this class are cloneable with this method.
Usage
GceToken$clone(deep = FALSE)
Arguments
deepWhether to make a deep clone.
Token for use with workload identity federation
Description
Not intended for direct use. See credentials_external_account() instead.
Super classes
httr::Token -> httr::Token2.0 -> WifToken
Methods
Public methods
Inherited methods
WifToken$new()
Get a token via workload identity federation
Usage
WifToken$new(params = list())
Arguments
paramsA list of parameters for
init_oauth_external_account().
Returns
A WifToken.
WifToken$init_credentials()
Enact the actual token exchange for workload identity federation.
Usage
WifToken$init_credentials()
WifToken$refresh()
Refreshes the token, which means re-doing the entire token flow in this case.
Usage
WifToken$refresh()
WifToken$format()
Format a WifToken().
Usage
WifToken$format(...)
Arguments
...Not used.
WifToken$print()
Print a WifToken().
Usage
WifToken$print(...)
Arguments
...Not used.
WifToken$can_refresh()
Placeholder implementation of required method. Returns TRUE.
Usage
WifToken$can_refresh()
WifToken$cache()
Placeholder implementation of required method. Returns self.
Usage
WifToken$cache()
WifToken$load_from_cache()
Placeholder implementation of required method. Returns self.
Usage
WifToken$load_from_cache()
WifToken$validate()
Placeholder implementation of required method.
Usage
WifToken$validate()
WifToken$revoke()
Placeholder implementation of required method.
Usage
WifToken$revoke()
WifToken$clone()
The objects of this class are cloneable with this method.
Usage
WifToken$clone(deep = FALSE)
Arguments
deepWhether to make a deep clone.
Abbreviate a bullet list neatly
Description
For internal use in gargle, googledrive, and googlesheets4 (for now).
Usage
bulletize(x, bullet = "*", n_show = 5, n_fudge = 2)
Check for a service account
Description
This pre-checks information provided to a high-level, user-facing auth
function, such as googledrive::drive_auth(), before passing the user's
input along to token_fetch(), which is designed to silently swallow errors.
Some users are confused about the difference between an OAuth client and a
service account and they provide the (path to the) JSON for one, when the
other is what's actually expected.
Usage
check_is_service_account(path, hint, call = caller_env())
Arguments
path |
JSON identifying the service account, in one of the forms
supported for the |
hint |
The relevant function to call for configuring an OAuth client. |
call |
The execution environment of a currently running
function, e.g. You only need to supply Can also be For more information about error calls, see Including function calls in error messages. |
Value
Nothing. Exists purely to throw an error.
Credential function registry
Description
Functions to query or manipulate the registry of credential functions
consulted by token_fetch().
Usage
cred_funs_list()
cred_funs_add(...)
cred_funs_set(funs, ls = deprecated())
cred_funs_clear()
cred_funs_list_default()
cred_funs_set_default()
local_cred_funs(
funs = cred_funs_list_default(),
action = c("replace", "modify"),
.local_envir = caller_env()
)
with_cred_funs(
funs = cred_funs_list_default(),
code,
action = c("replace", "modify")
)
Arguments
... |
< |
funs |
A named list of credential functions. |
ls |
|
action |
Whether to use
|
.local_envir |
The environment to use for scoping. Defaults to current execution environment. |
code |
Code to run with temporary credential function registry. |
Value
A list of credential functions or NULL.
Functions
-
cred_funs_list(): Get the list of registered credential functions. -
cred_funs_add(): Register one or more new credential fetching functions. Function(s) are added to the front of the list. So:"First registered, last tried."
"Last registered, first tried."
Can also be used to remove a function from the registry.
-
cred_funs_set(): Register a list of credential fetching functions. -
cred_funs_clear(): Clear the credential function registry. -
cred_funs_list_default(): Return the default list of credential functions. -
cred_funs_set_default(): Reset the registry to the gargle default. -
local_cred_funs(): Modify the credential function registry in the current scope. It is an example of thelocal_*()functions in withr. -
with_cred_funs(): Evaluatecodewith a temporarily modified credential function registry. It is an example of thewith_*()functions in withr.
See Also
token_fetch(), which is where the registry is actually used.
Examples
names(cred_funs_list())
creds_one <- function(scopes, ...) {}
cred_funs_add(one = creds_one)
cred_funs_add(two = creds_one, three = creds_one)
names(cred_funs_list())
cred_funs_add(two = NULL)
names(cred_funs_list())
# restore the default list
cred_funs_set_default()
# remove one specific credential fetcher
cred_funs_add(credentials_gce = NULL)
names(cred_funs_list())
# force the use of one specific credential fetcher
cred_funs_set(list(credentials_user_oauth2 = credentials_user_oauth2))
names(cred_funs_list())
# restore the default list
cred_funs_set_default()
# run some code with a temporary change to the registry
# creds_one ONLY
with_cred_funs(
list(one = creds_one),
names(cred_funs_list())
)
# add creds_one to the list
with_cred_funs(
list(one = creds_one),
names(cred_funs_list()),
action = "modify"
)
# remove credentials_gce
with_cred_funs(
list(credentials_gce = NULL),
names(cred_funs_list()),
action = "modify"
)
Load Application Default Credentials
Description
Loads credentials from a file identified via a search strategy known as
Application Default Credentials (ADC). The hope is to make auth "just work"
for someone working on Google-provided infrastructure or who has used Google
tooling to get started, such as the gcloud command line tool.
A sequence of paths is consulted, which we describe here, with some abuse of
notation. ALL_CAPS represents the value of an environment variable and %||%
is used in the spirit of a null coalescing operator.
GOOGLE_APPLICATION_CREDENTIALS CLOUDSDK_CONFIG/application_default_credentials.json # on Windows: (APPDATA %||% SystemDrive %||% C:)\gcloud\application_default_credentials.json # on not-Windows: ~/.config/gcloud/application_default_credentials.json
If the above search successfully identifies a JSON file, it is parsed and
ingested as a service account, an external account ("workload identity
federation"), or a user account. Literally, if the JSON describes a service
account, we call credentials_service_account() and if it describes an
external account, we call credentials_external_account().
Usage
credentials_app_default(
scopes = "https://www.googleapis.com/auth/cloud-platform",
...,
subject = NULL
)
Arguments
scopes |
A character vector of scopes to request. Pick from those listed at https://developers.google.com/identity/protocols/oauth2/scopes. For certain token flows, the
|
... |
Additional arguments passed to all credential functions. |
subject |
An optional subject claim. Specify this if you wish to use the
service account represented by |
Value
An httr::TokenServiceAccount, a WifToken,
an httr::Token2.0 or NULL.
See Also
Other credential functions:
credentials_byo_oauth2(),
credentials_external_account(),
credentials_gce(),
credentials_service_account(),
credentials_user_oauth2(),
token_fetch()
Examples
## Not run:
credentials_app_default()
## End(Not run)
Load a user-provided token
Description
This function is designed to pass its token input through, after doing a
few checks and some light processing:
If
tokenhas classrequest, i.e. it is a token that has been prepared withhttr::config(), theauth_tokencomponent is extracted. For example, such input could be returned bygoogledrive::drive_token()orbigrquery::bq_token().If
tokenis an instance ofGargle2.0(so: a gargle-obtained user token), checks that it appears to be a Google OAuth token, based on its embeddedoauth_endpoint. Refreshes the token, if it's refreshable.Returns the
token.
There is no point in providing scopes. They are ignored because the
scopes associated with the token have already been baked in to the token
itself and gargle does not support incremental authorization. The main point
of credentials_byo_oauth2() is to allow token_fetch() (and packages that
wrap it) to accommodate a "bring your own token" workflow.
This also makes it possible to obtain a token with one package and then register it for use with another package. For example, the default scope requested by googledrive is also sufficient for operations available in googlesheets4. You could use a shared token like so:
library(googledrive) library(googlesheets4) drive_auth(email = "jane_doe@example.com") gs4_auth(token = drive_token()) # work with both packages freely now, with the same identity
Usage
credentials_byo_oauth2(scopes = NULL, token, ...)
Arguments
scopes |
A character vector of scopes to request. Pick from those listed at https://developers.google.com/identity/protocols/oauth2/scopes. For certain token flows, the
|
token |
A token with class Token2.0 or an object of
httr's class |
... |
Additional arguments passed to all credential functions. |
Value
An Token2.0.
See Also
Other credential functions:
credentials_app_default(),
credentials_external_account(),
credentials_gce(),
credentials_service_account(),
credentials_user_oauth2(),
token_fetch()
Examples
## Not run:
# assume `my_token` is a Token2.0 object returned by a function such as
# credentials_user_oauth2()
credentials_byo_oauth2(token = my_token)
## End(Not run)
Get a token for an external account
Description
Workload identity federation lets applications running outside Google
Cloud, such as on AWS or GitHub Actions, access Google Cloud resources by
using a federated identity instead of a service account key. This
eliminates the dilemma of how to safely manage service account credential
files.
Unlike a service account key, the configuration for workload identity federation is not a long-lived secret that you need to store and protect. What the configuration looks like depends on the platform.
On AWS, it's a file of non-sensitive metadata that you download once and keep on the instance; the sensitive data is obtained "on-the-fly" at run time.
On GitHub Actions, the configuration file is written fresh for each job and contains only a short-lived credential.
The configuration is used to obtain a so-called subject token from the external identity provider, such as AWS or GitHub. The subject token is then sent to Google's Security Token Service API, in exchange for a very short-lived federated access token. Finally, the federated access token is sent to Google's Service Account Credentials API, in exchange for a short-lived GCP access token. This access token allows the external application to impersonate a service account and inherit the permissions of the service account to access GCP resources.
This feature is still experimental in gargle. The credential_source in
the configuration determines how the subject token is obtained and gargle
supports these types:
AWS (
"environment_id": "aws1"). This only works when running on an EC2 instance and requires the suggested packages aws.signature and aws.ec2metadata.URL-sourced credentials (
"url"). The subject token is fetched from a URL, with optional requestheaders. Thegoogle-github-actions/authaction writes this type of configuration for GitHub Actions and points theGOOGLE_APPLICATION_CREDENTIALSenvironment variable at it. That means that, in a workflow that runs this action,token_fetch()(and, therefore, the auth functions of client packages) can discover and use the credentials viacredentials_app_default().File-sourced credentials (
"file"). The subject token is read from a local file.
For URL- and file-sourced credentials, the subject token is either the
entire response or file ("format": {"type": "text"}, the default) or a
field in a JSON object ("format": {"type": "json", "subject_token_field_name": "..."}).
gargle does not support executable-sourced credentials. The configuration
must include service_account_impersonation_url, i.e. gargle does not yet
support direct workload identity federation, without service account
impersonation. If you would like gargle to support additional variations
of this token flow, please open an issue on GitHub and describe your use case.
Usage
credentials_external_account(
scopes = "https://www.googleapis.com/auth/cloud-platform",
path = "",
...
)
Arguments
scopes |
A character vector of scopes to request. Pick from those listed at https://developers.google.com/identity/protocols/oauth2/scopes. For certain token flows, the
|
path |
JSON containing the workload identity configuration for the
external account, in one of the forms supported for the Note that external account tokens are a natural fit for use as Application
Default Credentials, so consider storing the configuration file in one of
the standard locations consulted for ADC, instead of providing |
... |
Additional arguments passed to all credential functions. |
Value
A WifToken() or NULL.
See Also
Most of the setup for this authentication method happens on the GCP side; the external platform typically needs little or no configuration. These links provide, respectively, a high-level overview, step-by-step instructions, and Google's specification for the configuration file.
Other credential functions:
credentials_app_default(),
credentials_byo_oauth2(),
credentials_gce(),
credentials_service_account(),
credentials_user_oauth2(),
token_fetch()
Examples
## Not run:
credentials_external_account()
## End(Not run)
Get a token from the Google metadata server
Description
If your code is running on Google Cloud, we can often obtain a token for an
attached service account directly from a metadata server. This is more secure
than working with an explicit a service account key, as
credentials_service_account() does, and is the preferred method of auth for
workloads running on Google Cloud.
The most straightforward scenario is when you are working in a VM on Google Compute Engine and it's OK to use the default service account. This should "just work" automatically.
credentials_gce() supports other use cases (such as GKE Workload Identity),
but may require some explicit setup, such as:
Create a service account, grant it appropriate scopes(s) and IAM roles, attach it to the target resource. This prep work happens outside of R, e.g., in the Google Cloud Console. On the R side, provide the email address of this appropriately configured service account via
service_account.Specify details for constructing the root URL of the metadata service:
The logical option
"gargle.gce.use_ip". If undefined, this defaults toFALSE.The environment variable
GCE_METADATA_URLis consulted when"gargle.gce.use_ip"isFALSE. If undefined, the default ismetadata.google.internal.The environment variable
GCE_METADATA_IPis consulted when"gargle.gce.use_ip"isTRUE. If undefined, the default is169.254.169.254.
Change (presumably increase) the timeout for requests to the metadata server via the
"gargle.gce.timeout"global option. This timeout is given in seconds and is set to a value (strategy, really) that often works well in practice. However, in some cases it may be necessary to increase the timeout with code such as:
options(gargle.gce.timeout = 3)
For details on specific use cases, such as Google Kubernetes Engine (GKE),
see vignette("non-interactive-auth").
Usage
credentials_gce(
scopes = "https://www.googleapis.com/auth/cloud-platform",
service_account = "default",
...
)
Arguments
scopes |
A character vector of scopes to request. Pick from those listed at https://developers.google.com/identity/protocols/oauth2/scopes. For certain token flows, the
|
service_account |
Name of the GCE service account to use. |
... |
Additional arguments passed to all credential functions. |
Value
A GceToken() or NULL.
See Also
A related auth flow that can be used on certain non-Google
platforms, such as AWS or GitHub Actions, is workload identity federation,
which is implemented in credentials_external_account().
https://docs.cloud.google.com/compute/docs/access/service-accounts
https://docs.cloud.google.com/iam/docs/best-practices-service-accounts
How to attach a service account to a resource: https://cloud.google.com/iam/docs/impersonating-service-accounts#attaching-to-resources
https://docs.cloud.google.com/kubernetes-engine/docs/concepts/workload-identity
https://docs.cloud.google.com/kubernetes-engine/docs/how-to/workload-identity
https://docs.cloud.google.com/compute/docs/metadata/overview
Other credential functions:
credentials_app_default(),
credentials_byo_oauth2(),
credentials_external_account(),
credentials_service_account(),
credentials_user_oauth2(),
token_fetch()
Examples
## Not run:
credentials_gce()
## End(Not run)
Load a service account token
Description
Load a service account token
Usage
credentials_service_account(scopes = NULL, path = "", ..., subject = NULL)
Arguments
scopes |
A character vector of scopes to request. Pick from those listed at https://developers.google.com/identity/protocols/oauth2/scopes. For certain token flows, the
|
path |
JSON identifying the service account, in one of the forms
supported for the |
... |
Additional arguments passed to all credential functions. |
subject |
An optional subject claim. Specify this if you wish to use the
service account represented by |
Details
Note that fetching a token for a service account requires a
reasonably accurate system clock. For more information, see the
vignette("how-gargle-gets-tokens").
Value
An httr::TokenServiceAccount or NULL.
See Also
Additional reading on delegation of domain-wide authority:
Other credential functions:
credentials_app_default(),
credentials_byo_oauth2(),
credentials_external_account(),
credentials_gce(),
credentials_user_oauth2(),
token_fetch()
Examples
## Not run:
token <- credentials_service_account(
scopes = "https://www.googleapis.com/auth/userinfo.email",
path = "/path/to/your/service-account.json"
)
## End(Not run)
Get an OAuth token for a user
Description
Consults the token cache for a suitable OAuth token and, if unsuccessful, gets a token via the browser flow. A cached token is suitable if it's compatible with the user's request in this sense:
OAuth client must be same.
Scopes must be same.
Email, if provided, must be same. If specified email is a glob pattern like
"*@example.com", email matching is done at the domain level.
gargle is very conservative about using OAuth tokens discovered in the user's
cache and will generally seek interactive confirmation. Therefore, in a
non-interactive setting, it's important to explicitly specify the "email"
of the target account or to explicitly authorize automatic discovery. See
gargle2.0_token(), which this function wraps, for more. Non-interactive use
also suggests it might be time to use a service account token or workload identity federation.
Usage
credentials_user_oauth2(
scopes = NULL,
client = gargle_client(),
package = "gargle",
...,
app = deprecated()
)
Arguments
scopes |
A character vector of scopes to request. Pick from those listed at https://developers.google.com/identity/protocols/oauth2/scopes. For certain token flows, the
|
client |
A Google OAuth client, preferably constructed via
|
package |
Name of the package requesting a token. Used in messages. |
... |
Arguments passed on to
|
app |
Value
A Gargle2.0 token.
See Also
Other credential functions:
credentials_app_default(),
credentials_byo_oauth2(),
credentials_external_account(),
credentials_gce(),
credentials_service_account(),
token_fetch()
Examples
## Not run:
# Drive scope, built-in gargle demo client
scopes <- "https://www.googleapis.com/auth/drive"
credentials_user_oauth2(scopes, client = gargle_client())
# bring your own client
client <- gargle_oauth_client_from_json(
path = "/path/to/the/JSON/you/downloaded/from/gcp/console.json",
name = "my-nifty-oauth-client"
)
credentials_user_oauth2(scopes, client)
## End(Not run)
Generate a field mask
Description
Many Google API requests take a field mask, via a fields parameter, in the
URL and/or in the body. field_mask() generates such a field mask from an R
list, typically a list that is destined to be part of the body of a request
that writes or updates a resource. field_mask() is designed to help in the
common case where the attributes you wish to modify are exactly the ones
represented in the object. It is possible to use a "larger" field mask, that
is either less specific or that explicitly includes other attributes, in
which case the attributes covered by the mask but absent from the object are
reset to default values. This is not exactly the use case field_mask() is
designed for, but its output could still be useful as a first step in
constructing such a mask.
Usage
field_mask(x)
Arguments
x |
A named R list, where the requirement for names applies at all levels, i.e. recursively. |
Value
A Google API field mask, as a string.
See Also
The documentation for the JSON encoding of a Protocol Buffers FieldMask.
Examples
x <- list(sheetId = 1234, title = "my_favorite_worksheet")
field_mask(x)
x <- list(
userEnteredFormat = list(
backgroundColor = list(
red = 159 / 255, green = 183 / 255, blue = 196 / 255
)
)
)
field_mask(x)
x <- list(
sheetId = 1234,
gridProperties = list(rowCount = 5, columnCount = 3)
)
field_mask(x)
Generate a gargle token
Description
Constructor function for objects of class Gargle2.0.
Usage
gargle2.0_token(
email = gargle_oauth_email(),
client = gargle_client(),
package = "gargle",
scope = NULL,
use_oob = gargle_oob_default(),
credentials = NULL,
cache = if (is.null(credentials)) gargle_oauth_cache() else FALSE,
...,
app = deprecated()
)
Arguments
email |
Optional. If specified,
Defaults to the option named |
client |
A Google OAuth client, preferably constructed via
|
package |
Name of the package requesting a token. Used in messages. |
scope |
A character vector of scopes to request. |
use_oob |
Whether to use out-of-band authentication (or, perhaps, a
variant implemented by gargle and known as "pseudo-OOB") when first
acquiring the token. Defaults to the value returned by
If the OAuth client is provided implicitly by a wrapper package, its type
probably defaults to the value returned by
|
credentials |
Advanced use only: allows you to completely customise token generation. |
cache |
Specifies the OAuth token cache. Defaults to the option named
|
... |
Absorbs arguments intended for use by other credential functions. Not used. |
app |
Value
An object of class Gargle2.0, either new or loaded from the cache.
Examples
## Not run:
gargle2.0_token()
## End(Not run)
API key for demonstration purposes
Description
Some APIs accept requests for public resources, in which case the request must be sent with an API key in lieu of a token. This function provides an API key for limited use in prototyping and for testing and documentation of gargle itself. This key may be deleted or rotated at any time. There are no guarantees about which APIs are enabled. DO NOT USE THIS IN A PACKAGE or for anything other than interactive, small-scale experimentation.
You can get your own API key, without these limitations. See the How to get your own API credentials vignette for more details.
Usage
gargle_api_key()
Examples
gargle_api_key()
OAuth client for demonstration purposes
Description
Invisibly returns an instance of
gargle_oauth_client that can be used to test drive
gargle before obtaining your own client ID and secret. This OAuth client may
be deleted or rotated at any time. There are no guarantees about which APIs
are enabled. DO NOT USE THIS IN A PACKAGE or for anything other than
interactive, small-scale experimentation.
You can get your own OAuth client ID and secret, without these limitations.
See the vignette("get-api-credentials") for more details.
Usage
gargle_client(type = NULL)
Arguments
type |
Specifies the type of OAuth client. The valid values are a subset of possible Google client types and reflect the key used to describe the client in its JSON representation:
|
Value
An OAuth client, produced by gargle_oauth_client(), invisibly.
Examples
## Not run:
gargle_client()
## End(Not run)
Access the last response
Description
These functions give access to the most recent response processed by
response_process(..., remember = TRUE). They can be
useful for post mortem analysis of puzzling or failed API interactions.
Usage
gargle_last_response()
gargle_last_content()
Value
-
gargle_last_response()returns the most recenthttr::response()object. -
gargle_last_content()returns the parsed JSON content from the most recent response or an empty list if unavailable.
Map a cli-styled template over an object
Description
For internal use in gargle, googledrive, and googlesheets4 (for now).
Usage
gargle_map_cli(x, ...)
Create an OAuth client for Google
Description
A gargle_oauth_client consists of:
A type. gargle only supports the "Desktop app" and "Web application" client types. Different types are associated with different OAuth flows.
A client ID and secret.
Optionally, one or more redirect URIs.
A name. This is really a human-facing label. Or, rather, it can be used that way, but the default is just a hash. We recommend using the same name here as the name used to label the client ID in the Google Cloud Platform Console.
A gargle_oauth_client is an adaptation of httr's oauth_app() (currently)
and httr2's oauth_client() (which gargle will migrate to in the future).
Usage
gargle_oauth_client_from_json(path, name = NULL)
gargle_oauth_client(
id,
secret,
redirect_uris = NULL,
type = c("installed", "web"),
name = hash(id)
)
Arguments
path |
JSON downloaded from Google Cloud Console, containing a client id and
secret, in one of the forms supported for the |
name |
A label for this specific client, presumably the same name used to label it in Google Cloud Console. Unfortunately there is no way to make that true programmatically, i.e. the JSON representation does not contain this information. |
id |
Client ID |
secret |
Client secret |
redirect_uris |
Where your application listens for the response from Google's authorization server. If you didn't configure this specifically when creating the client (which is only possible for clients of the "web" type), you can leave this unspecified. |
type |
Specifies the type of OAuth client. The valid values are a subset of possible Google client types and reflect the key used to describe the client in its JSON representation:
|
Value
An OAuth client: An S3 list with class gargle_oauth_client. For
backwards compatibility reasons, this currently also inherits from the httr
S3 class oauth_app, but that is a temporary measure. An instance of
gargle_oauth_client stores more information than httr's oauth_app, such
as the OAuth client's type ("web" or "installed").
There are some redundant fields in this object during the httr-to-httr2
transition period. The legacy fields appname and key repeat the
information in the future-facing fields name and (client) id. Prefer
name and id to appname and key in downstream code. Prefer the
constructors gargle_oauth_client_from_json() and gargle_oauth_client()
to httr::oauth_app() and oauth_app_from_json().
Examples
## Not run:
gargle_oauth_client_from_json(
path = "/path/to/the/JSON/you/downloaded/from/gcp/console.json",
name = "my-nifty-oauth-client"
)
## End(Not run)
gargle_oauth_client(
id = "some_long_id",
secret = "ssshhhhh_its_a_secret",
name = "my-nifty-oauth-client"
)
OAuth token situation report
Description
Get a human-oriented overview of the existing gargle OAuth tokens:
Filepath of the current cache
Number of tokens found there
Compact summary of the associated
Email = Google identity
OAuth client (actually, just its nickname)
Scopes
Hash (actually, just the first 7 characters)
This is the most direct way to find out where gargle's OAuth cache is (see
gargle_oauth_cache() for more about the cache location). The filepath
column of the returned data frame makes it easy to delete specific tokens,
e.g.:
dat <- gargle_oauth_sitrep() # delete all cached tokens for one Google identity unlink(dat$filepath[dat$email == "jane@example.com"])
Usage
gargle_oauth_sitrep(cache = NULL)
Arguments
cache |
Specifies the OAuth token cache. Defaults to the option named
|
Value
A data frame with one row per cached token, invisibly. Note this data
frame contains more columns than it seems, e.g. the filepath column
isn't printed by default.
Examples
gargle_oauth_sitrep()
Options consulted by gargle
Description
Wrapper functions around options consulted by gargle, which provide:
A place to hang documentation.
The mechanism for setting a default.
If the built-in defaults don't suit you, set one or more of these options.
Typically, this is done in the .Rprofile startup file, with code along
these lines:
options( gargle_oauth_email = "jane@example.com", gargle_oauth_cache = "/path/to/folder/that/does/not/sync/to/cloud" )
Usage
gargle_oauth_email()
gargle_oob_default()
gargle_oauth_cache()
gargle_oauth_client_type()
gargle_verbosity()
local_gargle_verbosity(level, env = caller_env())
with_gargle_verbosity(level, code)
Arguments
level |
Verbosity level: "debug" > "info" > "silent" |
env |
The environment to use for scoping |
code |
Code to execute with specified verbosity level |
gargle_oauth_email
gargle_oauth_email() returns the option named "gargle_oauth_email", which
is undefined by default. If set, this option should be one of:
An actual email address corresponding to your preferred Google identity. Example:
janedoe@gmail.com.A glob pattern that indicates your preferred Google domain. Example:
*@example.com.-
TRUEto allow email and OAuth token auto-discovery, if exactly one suitable token is found in the cache. -
FALSEorNAto force the OAuth dance in the browser.
gargle_oob_default
gargle_oob_default() returns TRUE unconditionally on RStudio Server,
Posit Workbench, Posit Cloud, or Google Colaboratory, since it is not
possible to launch a local web server in these contexts. In this case, for
the final step of the OAuth dance, the user is redirected to a specific URL
where they must copy a code and paste it back into the R session.
In all other contexts, gargle_oob_default() consults the option named
"gargle_oob_default", then the option named "httr_oob_default", and
eventually defaults to FALSE.
"oob" stands for out-of-band. Read more about out-of-band authentication in
the vignette vignette("auth-from-web").
gargle_oauth_cache
gargle_oauth_cache() returns the option named "gargle_oauth_cache",
defaulting to NA. If defined, the option must be set to a logical value or
a string:
-
TRUEmeans to cache tokens in the default user-level cache directory, given byrappdirs::user_cache_dir("gargle"). -
FALSEmeans don't cache. A string is interpreted as the path to a folder to use as the cache.
The NA default means the default cache directory is used, if it already
exists. Otherwise, in an interactive session, gargle asks the user for
permission to create the cache. The outcome of this is stored in the
"gargle_oauth_cache" option as TRUE or FALSE for the rest of the session.
Use gargle_oauth_sitrep() to see exactly where the cache is and which
tokens it holds.
gargle_oauth_client_type
gargle_oauth_client_type() returns the option named
"gargle_oauth_client_type", if defined. If defined, the option must be either
"installed" or "web". If the option is not defined, the function returns:
"web" on RStudio Server, Posit Workbench, Posit Cloud, or Google Colaboratory
"installed" otherwise
Primarily intended to help infer the most suitable OAuth client type when a user is relying on a built-in client, such as the tidyverse client used by packages like bigrquery, googledrive, and googlesheets4.
gargle_verbosity
gargle_verbosity() returns the option named "gargle_verbosity", which
determines gargle's verbosity. There are three possible values, inspired by
the logging levels of log4j:
"debug": Fine-grained information helpful when debugging, e.g. figuring out how
token_fetch()is working through the registry of credential functions. Previously, this was activated by setting an option named "gargle_quiet" toFALSE."info" (default): High-level information that a typical user needs to see. Since typical gargle usage is always indirect, i.e. gargle is called by another package, gargle itself is very quiet. There are very few messages emitted when
gargle_verbosity = "info"."silent": No messages at all. However, warnings or errors are still thrown normally.
Examples
gargle_oauth_email()
gargle_oob_default()
gargle_oauth_cache()
gargle_oauth_client_type()
gargle_verbosity()
Encrypt/decrypt JSON or an R object
Description
These functions help to encrypt and decrypt confidential information that you might need when deploying gargle-using projects or in CI/CD. They basically rely on inlined copies of the secret functions in the httr2 package. The awkwardness of inlining code from httr2 can be removed if/when gargle starts to depend on httr2.
The
secret_encrypt_json()+secret_decrypt_json()pair is unique to gargle, given how frequently Google auth relies on JSON files, e.g., service account tokens and OAuth clients.The
secret_write_rds()+secret_read_rds()pair is just a copy of functions from httr2. They are handy if you need to secure a user token.-
secret_make_key()andsecret_has_key()are also copies of functions from httr2. Usesecret_make_keyto generate a key. Usesecret_has_key()to condition on key availability in, e.g., examples, tests, or apps.
Usage
secret_encrypt_json(json, path = NULL, key)
secret_decrypt_json(path, key)
secret_make_key()
secret_write_rds(x, path, key)
secret_read_rds(path, key)
secret_has_key(key)
Arguments
json |
A JSON file (or string). |
path |
The path to write to ( |
key |
Encryption key, as implemented by httr2's secret functions. This should
almost always be the name of an environment variable whose value was
generated with |
x |
An R object. |
Value
-
secret_encrypt_json(): The encrypted JSON string, invisibly. In typical use, this function is mainly called for its side effect, which is to write an encrypted file. -
secret_decrypt_json(): The decrypted JSON string, invisibly. -
secret_write_rds():x, invisibly -
secret_read_rds(): the decrypted object. -
secret_make_key(): a random string to use as an encryption key. -
secret_has_key()returnsTRUEif the key is available andFALSEotherwise.
Examples
# gargle ships with JSON for a fake service account
# here we put the encrypted JSON into a new file
tmp <- tempfile()
secret_encrypt_json(
fs::path_package("gargle", "extdata", "fake_service_account.json"),
tmp,
key = "GARGLE_KEY"
)
# complete the round trip by providing the decrypted JSON to a credential
# function
credentials_service_account(
scopes = "https://www.googleapis.com/auth/userinfo.email",
path = secret_decrypt_json(
fs::path_package("gargle", "secret", "gargle-testing.json"),
key = "GARGLE_KEY"
)
)
file.remove(tmp)
# make an artificial Gargle2.0 token
fauxen <- gargle2.0_token(
email = "jane@example.org",
client = gargle_oauth_client(
id = "CLIENT_ID", secret = "SECRET", name = "CLIENT"
),
credentials = list(token = "fauxen"),
cache = FALSE
)
fauxen
# store the fake token in an encrypted file
tmp2 <- tempfile()
secret_write_rds(fauxen, path = tmp2, key = "GARGLE_KEY")
# complete the round trip by providing the decrypted token to the "BYO token"
# credential function
rt_fauxen <- credentials_byo_oauth2(
token = secret_read_rds(tmp2, key = "GARGLE_KEY")
)
rt_fauxen
file.remove(tmp2)
Fetch access token for a service account on GCE
Description
Fetch access token for a service account on GCE
Usage
gce_access_token(
scopes = "https://www.googleapis.com/auth/cloud-platform",
service_account = "default"
)
Arguments
scopes |
A character vector of scopes to request. Pick from those listed at https://developers.google.com/identity/protocols/oauth2/scopes. For certain token flows, the
|
service_account |
Name of the GCE service account to use. |
List all service accounts available on this GCE instance
Description
List all service accounts available on this GCE instance
Usage
gce_instance_service_accounts()
Value
A data frame, where each row is a service account. Due to aliasing, there is no guarantee that each row represents a distinct service account.
See Also
The return value is built from a recursive query of the so-called "directory" of the instance's service accounts as documented in https://cloud.google.com/compute/docs/metadata/default-metadata-values#vm_instance_metadata.
Examples
credentials_gce()
Create an AuthState
Description
Constructor function for objects of class AuthState.
Usage
init_AuthState(
package = NA_character_,
client = NULL,
api_key = NULL,
auth_active = TRUE,
cred = NULL,
app = deprecated()
)
Arguments
package |
Package name, an optional string. It is recommended to record the name of the package whose auth state is being managed. Ultimately, this may be used in some downstream messaging. |
client |
A Google OAuth client, preferably constructed via
|
api_key |
Optional. API key (a string). Some APIs accept unauthorized, "token-free" requests for public resources, but only if the request includes an API key. |
auth_active |
Logical. |
cred |
Credentials. Typically populated indirectly via |
app |
Value
An object of class AuthState.
Examples
my_client <- gargle_oauth_client(
id = "some_long_client_id",
secret = "ssshhhhh_its_a_secret",
name = "my-nifty-oauth-client"
)
init_AuthState(
package = "my_package",
client = my_client,
api_key = "api_key_api_key_api_key",
)
Assets for internal use
Description
Assets for use inside specific packages maintained by the tidyverse team.
Usage
tidyverse_api_key()
tidyverse_client(type = NULL)
tidyverse_app()
Create an OAuth app from JSON
Description
oauth_app_from_json() is being replaced with
gargle_oauth_client_from_json(), in light of the new
gargle_oauth_client class. Now oauth_app_from_json() potentially warns
about this deprecation and immediately passes its inputs through to
gargle_oauth_client_from_json().
gargle_app() is being replaced with gargle_client().
Usage
oauth_app_from_json(path, appname = NULL)
gargle_app()
Arguments
path |
JSON downloaded from Google Cloud Console, containing a client id and
secret, in one of the forms supported for the |
appname |
name of the application. This is not used for OAuth, but is used to make it easier to identify different applications. |
Generate OAuth token for an external account
Description
Generate OAuth token for an external account
Usage
oauth_external_token(
path = "",
scopes = "https://www.googleapis.com/auth/cloud-platform"
)
Arguments
path |
JSON containing the workload identity configuration for the
external account, in one of the forms supported for the Note that external account tokens are a natural fit for use as Application
Default Credentials, so consider storing the configuration file in one of
the standard locations consulted for ADC, instead of providing |
scopes |
A character vector of scopes to request. Pick from those listed at https://developers.google.com/identity/protocols/oauth2/scopes. For certain token flows, the
|
Build a Google API request
Description
Intended primarily for internal use in client packages that provide
high-level wrappers for users. The vignette("request-helper-functions")
describes how one might use these functions inside a wrapper package.
Usage
request_develop(
endpoint,
params = list(),
base_url = "https://www.googleapis.com"
)
request_build(
method = "GET",
path = "",
params = list(),
body = list(),
token = NULL,
key = NULL,
base_url = "https://www.googleapis.com"
)
Arguments
endpoint |
List of information about the target endpoint or, in Google's vocabulary, the target "method". Presumably prepared from the Discovery Document for the target API. |
params |
Named list. Values destined for URL substitution, the query,
or, for |
base_url |
Character. |
method |
Character. An HTTP verb, such as |
path |
Character. Path to the resource, not including the API's
|
body |
List. Values to send in the API request body. |
token |
Token, ready for inclusion in a request, i.e. prepared with
|
key |
API key. Needed for requests that don't contain a token. For more,
see Google's document Credentials, access, security, and identity
( |
Value
request_develop(): list() with components method, path, params,
body, and base_url.
request_build(): list() with components method, url (the full URL,
post-substitution, including the query), body, token, and headers (a
named character vector holding the X-goog-api-key header, or NULL).
request_develop()
Combines user input (params) with information about an API endpoint.
endpoint should contain these components:
-
path: See documentation for argument. -
method: See documentation for argument. -
parameters: Compared withparamssupplied by user. An error is thrown if user-suppliedparamsaren't named inendpoint$parametersor if user fails to supply all required parameters. In the return value, body parameters are separated from those destined for path substitution or the query.
The return value is typically used as input to request_build().
request_build()
Builds a request, in a purely mechanical sense. This function does nothing specific to any particular Google API or endpoint.
Use with the output of
request_develop()or with hand-crafted input.-
paramsare used for variable substitution inpath. Leftoverparamsthat are not bound by thepathtemplate automatically become HTTP query parameters. Adds an API key, in the
X-goog-api-keyheader, if and only iftoken = NULLand removes the API key otherwise. Client packages should generally pass their own API key in, but note thatgargle_api_key()is available for small-scale experimentation.Client packages should send the request with
request_make()orrequest_retry(), which apply theheaders. Code that makes its own HTTP call with only theurlwon't send the API key.
See googledrive::generate_request() for an example of usage in a client
package. googledrive has an internal list of selected endpoints, derived from
the Drive API Discovery Document
(https://www.googleapis.com/discovery/v1/apis/drive/v3/rest),
exposed via googledrive::drive_endpoints(). An element from such a list is
the expected input for endpoint. googledrive::generate_request() is a
wrapper around request_develop() and request_build() that inserts a
googledrive-managed API key and some logic about Team Drives. All user-facing
functions use googledrive::generate_request() under the hood.
See Also
Other requests and responses:
request_make(),
response_process()
Examples
## Not run:
## Example with a prepared endpoint
ept <- googledrive::drive_endpoints("drive.files.update")[[1]]
req <- request_develop(
ept,
params = list(
fileId = "abc",
addParents = "123",
description = "Exciting File"
)
)
req
req <- request_build(
method = req$method,
path = req$path,
params = req$params,
body = req$body,
token = "PRETEND_I_AM_A_TOKEN"
)
req
## Example with no previous knowledge of the endpoint
## List a file's comments
## https://developers.google.com/drive/v3/reference/comments/list
req <- request_build(
method = "GET",
path = "drive/v3/files/{fileId}/comments",
params = list(
fileId = "your-file-id-goes-here",
fields = "*"
),
token = "PRETEND_I_AM_A_TOKEN"
)
req
## End(Not run)
# Example with no previous knowledge of the endpoint and no token
# find books by Hadley Wickham with the Books API,
# using gargle's demo API key (for which the Books API is enabled)
req <- request_build(
method = "GET",
path = "books/v1/volumes",
params = list(
q = "inauthor:Hadley Wickham",
maxResults = 10
),
key = gargle_api_key()
)
resp <- request_make(req)
out <- response_process(resp)
books <- lapply(out$items, \(x) x$volumeInfo)
data.frame(
title = vapply(books, \(x) x$title, character(1)),
authors = vapply(books, \(x) toString(x$authors), character(1)),
date = vapply(books, \(x) toString(x$publishedDate), character(1))
)
Make a Google API request
Description
Intended primarily for internal use in client packages that provide
high-level wrappers for users. request_make() does relatively little:
Calls an HTTP method.
Adds a user agent.
Adds any
headers, such as the API key header added byrequest_build().Enforces
"json"as the default forencode. This differs from httr's default behaviour, but aligns better with Google APIs.
Typically the input is created with request_build() and the output is
processed with response_process().
Usage
request_make(x, ..., encode = "json", user_agent = gargle_user_agent())
Arguments
x |
List. Holds the components for an HTTP request, presumably created
with |
... |
Optional arguments passed through to the HTTP method. Currently neither gargle nor httr checks that all are used, so be aware that unused arguments may be silently ignored. |
encode |
If the body is a named list, how should it be encoded? Can be one of form (application/x-www-form-urlencoded), multipart, (multipart/form-data), or json (application/json). For "multipart", list elements can be strings or objects created by
|
user_agent |
A user agent string, prepared by |
Value
Object of class response from httr.
See Also
Other requests and responses:
request_develop(),
response_process()
Examples
## Not run:
req <- gargle::request_build(
method = "GET",
path = "path/to/the/resource",
token = "PRETEND_I_AM_TOKEN"
)
gargle::request_make(req)
## End(Not run)
Make a Google API request, repeatedly
Description
Intended primarily for internal use in client packages that provide
high-level wrappers for users. It is a drop-in substitute for
request_make() that also has the ability to retry the request. Codes that
are considered retryable: 408, 429, 500, 502, 503.
Usage
request_retry(..., max_tries_total = 5, max_total_wait_time_in_seconds = 100)
Arguments
... |
Passed along to |
max_tries_total |
Maximum number of tries. |
max_total_wait_time_in_seconds |
Total seconds we are willing to dedicate to waiting, summed across all tries. This is a technical upper bound and actual cumulative waiting will be less. |
Details
Consider an example where we are willing to make a request up to 5 times.
try 1 2 3 4 5
|--|----|--------|----------------|
wait 1 2 3 4
There will be up to 5 - 1 = 4 waits and we generally want the waiting period
to get longer, in an exponential way. Such schemes are called exponential
backoff. request_retry() implements exponential backoff with "full jitter",
where each waiting time is generated from a uniform distribution, where the
interval of support grows exponentially. A common alternative is "equal
jitter", which adds some noise to fixed, exponentially increasing waiting
times.
Either way our waiting times are based on a geometric series, which, by convention, is usually written in terms of powers of 2:
b, 2b, 4b, 8b, ... = b * 2^0, b * 2^1, b * 2^2, b * 2^3, ...
The terms in this series require knowledge of b, the so-called exponential
base, and many retry functions and libraries require the user to specify
this. But most users find it easier to declare the total amount of waiting
time they can tolerate for one request. Therefore request_retry() asks for
that instead and solves for b internally. This is inspired by the Opnieuw
Python library for retries. Opnieuw's interface is designed to eliminate
uncertainty around:
Units: Is this thing given in seconds? minutes? milliseconds?
Ambiguity around how things are counted: Are we starting at 0 or 1? Are we counting tries or just the retries?
Non-intuitive required inputs, e.g., the exponential base.
Let n be the total number of tries we're willing to make (the argument
max_tries_total) and let W be the total amount of seconds we're willing
to dedicate to making and retrying this request (the argument
max_total_wait_time_in_seconds). Here's how we determine b:
sum_{i=0}^(n - 1) b * 2^i = W
b * sum_{i=0}^(n - 1) 2^i = W
b * ( (2 ^ n) - 1) = W
b = W / ( (2 ^ n) - 1)
Value
Object of class response from httr.
Special cases
request_retry() departs from exponential backoff in three special cases:
It actually implements truncated exponential backoff. There is a floor and a ceiling on random wait times.
-
Retry-Afterheader: If the response has a header namedRetry-After(case-insensitive), it is assumed to provide a non-negative integer indicating the number of seconds to wait. If present, we wait this many seconds and do not generate a random waiting time. (In theory, this header can alternatively provide a datetime after which to retry, but we have no first-hand experience with this variant for a Google API.) Sheets API quota exhaustion: In the course of googlesheets4 development, we've grown very familiar with the
429 RESOURCE_EXHAUSTEDerror. As of 2023-04-15, the Sheets API v4 has a limit of 300 requests per minute per project and 60 requests per minute per user per project. Limits for reads and writes are tracked separately. In our experience, the "60 (read or write) requests per minute per user" limit is the one you hit most often. If we detect this specific failure, the first wait time is a bit more than one minute, then we revert to exponential backoff.
See Also
-
https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/
-
https://www.channable.com/tech/opnieuw-a-simple-and-intuitive-retrying-library-for-python -
https://googleapis.dev/python/google-api-core/latest/retry.html
Examples
## Not run:
req <- gargle::request_build(
method = "GET",
path = "path/to/the/resource",
token = "PRETEND_I_AM_TOKEN"
)
gargle::request_retry(req)
## End(Not run)
Process a Google API response
Description
response_process() is intended primarily for internal use in client
packages that provide high-level wrappers for users. Typically applied as the
final step in this sequence of calls:
Request prepared with
request_build().Request made with
request_make().Response processed with
response_process().
All that's needed for a successful request is to parse the JSON extracted via
httr::content(). Therefore, the main point of response_process() is to
handle less happy outcomes:
Status codes in the 400s (client error) and 500s (server error). The structure of the error payload varies across Google APIs and we try to create a useful message for all variants we know about.
Non-JSON content type, such as HTML.
Status code in the 100s (information) or 300s (redirection). These are unexpected.
If response_process() results in an error, a redacted version of the resp
input is returned in the condition (auth tokens are removed).
Usage
response_process(
resp,
error_message = gargle_error_message,
error_class = NULL,
remember = TRUE,
call = caller_env()
)
response_as_json(resp, call = caller_env())
gargle_error_message(resp, call = caller_env())
Arguments
resp |
Object of class |
error_message |
Function that produces an informative error message from
the primary input, |
error_class |
Optional character vector of error classes to add to the
condition object. These classes are prepended to gargle's default classes
( |
remember |
Whether to remember the most recently processed response. |
call |
The execution environment of a currently running
function, e.g. You only need to supply Can also be For more information about error calls, see Including function calls in error messages. |
Details
When remember = TRUE (the default), gargle stores the most recently seen
response internally, for post hoc examination. The stored response is
literally just the most recent resp input, but with auth tokens redacted.
It can be accessed via gargle_last_response(). A companion function
gargle_last_content() returns just the parsed content, which is probably
the most useful form for post mortem analysis.
The response_as_json() helper is exported only as an aid to maintainers who
wish to use their own error_message function, instead of gargle's built-in
gargle_error_message(). When implementing a custom error_message
function, call response_as_json() immediately on the input in order to
inherit gargle's handling of non-JSON input.
Value
The content of the request, as a list. An HTTP status code of 204 (No
content) is a special case returning TRUE.
See Also
Other requests and responses:
request_develop(),
request_make()
Examples
## Not run:
# get an OAuth2 token with 'userinfo.email' scope
token <- token_fetch(scopes = "https://www.googleapis.com/auth/userinfo.email")
# see the email associated with this token
req <- gargle::request_build(
method = "GET",
path = "v1/userinfo",
token = token,
base_url = "https://openidconnect.googleapis.com"
)
resp <- gargle::request_make(req)
response_process(resp)
# make a bad request (this token has incorrect scope)
req <- gargle::request_build(
method = "GET",
path = "fitness/v1/users/{userId}/dataSources",
token = token,
params = list(userId = 12345)
)
resp <- gargle::request_make(req)
response_process(resp)
## End(Not run)
Get info from a token
Description
These functions send the token to Google endpoints that return info about a
token or a user.
Usage
token_userinfo(token)
token_email(token)
token_tokeninfo(token)
Arguments
token |
A token with class Token2.0 or an object of
httr's class |
Details
It's hard to say exactly what info will be returned by the "userinfo"
endpoint targetted by token_userinfo(). It depends on the token's scopes.
Where possible, OAuth2 tokens obtained via the gargle package include the
https://www.googleapis.com/auth/userinfo.email scope, which guarantees we
can learn the email associated with the token. If the token has the
https://www.googleapis.com/auth/userinfo.profile scope, there will be even
more information available. But for a token with unknown or arbitrary scopes,
we can't make any promises about what information will be returned.
Value
A list containing:
-
token_userinfo(): user info -
token_email(): user's email (obtained from a call totoken_userinfo()) -
token_tokeninfo(): token info
Examples
## Not run:
# with service account token
t <- token_fetch(
scopes = "https://www.googleapis.com/auth/drive",
path = "path/to/service/account/token/blah-blah-blah.json"
)
# or with an OAuth token
t <- token_fetch(
scopes = "https://www.googleapis.com/auth/drive",
email = "janedoe@example.com"
)
token_userinfo(t)
token_email(t)
tokens_tokeninfo(t)
## End(Not run)
Fetch a token for the given scopes
Description
This is a rather magical function that calls a series of concrete
credential-fetching functions, each wrapped in a tryCatch().
token_fetch() keeps trying until it succeeds or there are no more functions
to try. See the vignette("how-gargle-gets-tokens") for a full description
of token_fetch().
Usage
token_fetch(scopes = NULL, ...)
Arguments
scopes |
A character vector of scopes to request. Pick from those listed at https://developers.google.com/identity/protocols/oauth2/scopes. For certain token flows, the
|
... |
Additional arguments passed to all credential functions. |
Value
An httr::Token (often an instance of something
that inherits from httr::Token) or NULL.
See Also
cred_funs_list() reveals the current registry of
credential-fetching functions, in order.
Other credential functions:
credentials_app_default(),
credentials_byo_oauth2(),
credentials_external_account(),
credentials_gce(),
credentials_service_account(),
credentials_user_oauth2()
Examples
## Not run:
token_fetch(scopes = "https://www.googleapis.com/auth/userinfo.email")
## End(Not run)