Nothing
#' Global Configuration Options
#'
#' Configurable options that define vcr's default behavior.
#'
#' @param ... configuration settings used to override defaults. See below for a
#' complete list of valid arguments.
#'
#' @section Configurable settings:
#'
#' ## vcr options
#'
#' ### File locations
#'
#' - `dir` Cassette directory
#' - `write_disk_path` (character) path to write files to
#' for any requests that write responses to disk. by default this parameter
#' is `NULL`. For testing a package, you'll probably want this path to
#' be in your `tests/` directory, perhaps next to your cassettes
#' directory, e.g., where your cassettes are in `tests/fixtures`, your
#' files from requests that write to disk are in `tests/files`.
#' If you want to ignore these files in your installed package,
#' add them to `.Rinstignore`. If you want these files ignored on build
#' then add them to `.Rbuildignore` (though if you do, tests that depend
#' on these files probably will not work because they won't be found; so
#' you'll likely have to skip the associated tests as well).
#'
#' ### Contexts
#'
#' - `turned_off` (logical) VCR is turned on by default. Default:
#' `FALSE`
#' - `allow_unused_http_interactions` (logical) Default: `TRUE`
#' - `allow_http_connections_when_no_cassette` (logical) Determines how vcr
#' treats HTTP requests that are made when no vcr cassette is in use. When
#' `TRUE`, requests made when there is no vcr cassette in use will be allowed.
#' When `FALSE` (default), an [UnhandledHTTPRequestError] error will be raised
#' for any HTTP request made when there is no cassette in use
#'
#' ### Filtering
#'
#' - `ignore_hosts` (character) Vector of hosts to ignore. e.g., localhost, or
#' google.com. These hosts are ignored and real HTTP requests allowed to go
#' through
#' - `ignore_localhost` (logical) Default: `FALSE`
#' - `ignore_request` List of requests to ignore. NOT USED RIGHT NOW, sorry
#' - `filter_sensitive_data` named list of values to replace. Format is:
#' ```
#' list(thing_to_replace_it_with = thing_to_replace)
#' ```
#' We replace all instances of `thing_to_replace` with
#' `thing_to_replace_it_with`. Uses [gsub()] internally, with `fixed=TRUE`;
#' so does exact matches. Before recording (writing to a cassette) we do
#' the replacement and then when reading from the cassette we do the reverse
#' replacement to get back to the real data. Before record replacement happens
#' in internal function `write_interactions()`, while before playback
#' replacement happens in internal function `YAML$deserialize()`
#'
#' - `filter_sensitive_data_regex` named list of values to replace. Follows
#' `filter_sensitive_data` format, except uses `fixed=FALSE` in the [gsub()]
#' function call; this means that the value in `thing_to_replace` is a regex
#' pattern.
#'
#' - `filter_request_headers` (character/list) **request** headers to filter.
#' A character vector of request headers to remove - the headers will not be
#' recorded to disk. Alternatively, a named list similar to
#' `filter_sensitive_data` instructing vcr with what value to replace the
#' real value of the request header.
#' - `filter_response_headers` (named list) **response** headers to filter.
#' A character vector of response headers to remove - the headers will not be
#' recorded to disk. Alternatively, a named list similar to
#' `filter_sensitive_data` instructing vcr with what value to replace the
#' real value of the response header.
#' - `filter_query_parameters` (named list) query parameters to filter.
#' A character vector of query parameters to remove - the query parameters
#' will not be recorded to disk. Alternatively, a named list similar to
#' `filter_sensitive_data` instructing vcr with what value to replace the
#' real value of the query parameter.
#'
#' ## Errors
#'
#' - `verbose_errors` Do you want more verbose errors or less verbose
#' errors when cassette recording/usage fails? Default is `FALSE`, that is,
#' less verbose errors. If `TRUE`, error messages will include more details
#' about what went wrong and suggest possible solutions. For testing
#' in an interactive R session, if `verbose_errors=FALSE`, you can run
#' `vcr_last_error()` to get the full error. If in non-interactive mode,
#' which most users will be in when running the entire test suite for a
#' package, you can set an environment variable (`VCR_VERBOSE_ERRORS`)
#' to toggle this setting (e.g.,
#' `Sys.setenv(VCR_VERBOSE_ERRORS=TRUE); devtools::test()`)
#'
#' ### Internals
#'
#' - `cassettes` (list) don't use
#' - `linked_context` (logical) linked context
#' - `uri_parser` the uri parser, default: `crul::url_parse()`
#'
#' ### Logging
#'
#' - `log` (logical) should we log important vcr things? Default: `FALSE`
#' - `log_opts` (list) Additional logging options:
#' - 'file' either `"console"` or a file path to log to
#' - 'log_prefix' default: "Cassette". We insert the cassette name after
#' that prefix, then the rest of the message.
#' - More to come...
#'
#' ## Cassette Options
#'
#' These settings can be configured globally, using `vcr_configure()`, or
#' locally, using either `use_cassette()` or `insert_cassette()`. Global
#' settings are applied to *all* cassettes but are overridden by settings
#' defined locally for individual cassettes.
#'
#' - `record` (character) One of 'all', 'none', 'new_episodes', or 'once'.
#' See [recording]
#' - `match_requests_on` vector of matchers. Default: (`method`, `uri`)
#' See [request-matching] for details.
#' - `serialize_with`: (character) "yaml" or "json". Note that you can have
#' multiple cassettes with the same name as long as they use different
#' serializers; so if you only want one cassette for a given cassette name,
#' make sure to not switch serializers, or clean up files you no longer need.
#' - `json_pretty`: (logical) want JSON to be newline separated to be easier
#' to read? Or remove newlines to save disk space? default: FALSE
#' - `persist_with` (character) only option is "FileSystem"
#' - `preserve_exact_body_bytes` (logical) preserve exact body bytes for
#' - `re_record_interval` (numeric) When given, the cassette will be
#' re-recorded at the given interval, in seconds.
#' - `clean_outdated_http_interactions` (logical) Should outdated interactions
#' be recorded back to file. Default: `FALSE`
#' - `quiet` (logical) Suppress any messages from both vcr and webmockr.
#' Default: `TRUE`
#' - `warn_on_empty_cassette` (logical) Should a warning be thrown when an
#' empty cassette is detected? Empty cassettes are cleaned up (deleted) either
#' way. This option only determines whether a warning is thrown or not.
#' Default: `FALSE`
#'
#' @examples
#' vcr_configure(dir = tempdir())
#' vcr_configure(dir = tempdir(), record = "all")
#' vcr_configuration()
#' vcr_config_defaults()
#' vcr_configure(dir = tempdir(), ignore_hosts = "google.com")
#' vcr_configure(dir = tempdir(), ignore_localhost = TRUE)
#'
#'
#' # logging
#' vcr_configure(dir = tempdir(), log = TRUE,
#' log_opts = list(file = file.path(tempdir(), "vcr.log")))
#' vcr_configure(dir = tempdir(), log = TRUE, log_opts = list(file = "console"))
#' vcr_configure(dir = tempdir(), log = TRUE,
#' log_opts = list(
#' file = file.path(tempdir(), "vcr.log"),
#' log_prefix = "foobar"
#' ))
#' vcr_configure(dir = tempdir(), log = FALSE)
#'
#' # filter sensitive data
#' vcr_configure(dir = tempdir(),
#' filter_sensitive_data = list(foo = "<bar>")
#' )
#' vcr_configure(dir = tempdir(),
#' filter_sensitive_data = list(foo = "<bar>", hello = "<world>")
#' )
#' @export
vcr_configure <- function(...) {
params <- list(...)
invalid <- !names(params) %in% vcr_c$fields()
if (any(invalid)) {
warning(
"The following configuration parameters are not valid:",
sprintf("\n * %s", params[invalid]),
call. = FALSE
)
params <- params[!invalid]
}
if (length(params) == 0) return(vcr_c)
# TODO: Is this still the right place to change these settings?
ignore_hosts <- params$ignore_hosts
ignore_localhost <- params$ignore_localhost %||% FALSE
if (!is.null(ignore_hosts) || ignore_localhost) {
x <- RequestIgnorer$new()
if (!is.null(ignore_hosts)) x$ignore_hosts(hosts = ignore_hosts)
if (ignore_localhost) x$ignore_localhost()
}
for (i in seq_along(params)) {
vcr_c[[names(params)[i]]] <- params[[i]]
}
return(vcr_c)
}
#' @export
#' @rdname vcr_configure
vcr_configure_reset <- function() vcr_c$reset()
#' @export
#' @rdname vcr_configure
vcr_configuration <- function() vcr_c
#' @export
#' @rdname vcr_configure
vcr_config_defaults <- function() VCRConfig$new()$as_list()
VCRConfig <- R6::R6Class(
"VCRConfig",
private = list(
.dir = NULL,
.record = NULL,
.match_requests_on = NULL,
.allow_unused_http_interactions = NULL,
.serialize_with = NULL,
.json_pretty = NULL,
.persist_with = NULL,
.ignore_hosts = NULL,
.ignore_localhost = NULL,
.ignore_request = NULL,
.uri_parser = NULL,
.preserve_exact_body_bytes = NULL,
.turned_off = NULL,
.re_record_interval = NULL,
.clean_outdated_http_interactions = NULL,
.allow_http_connections_when_no_cassette = NULL,
.cassettes = NULL,
.linked_context = NULL,
.log = NULL,
.log_opts = NULL,
.filter_sensitive_data = NULL,
.filter_sensitive_data_regex = NULL,
.filter_request_headers = NULL,
.filter_response_headers = NULL,
.filter_query_parameters = NULL,
.write_disk_path = NULL,
.verbose_errors = NULL,
.quiet = NULL,
.warn_on_empty_cassette = NULL
),
active = list(
dir = function(value) {
if (missing(value)) return(private$.dir)
private$.dir <- value
},
record = function(value) {
if (missing(value)) return(private$.record)
private$.record <- check_record_mode(value)
},
match_requests_on = function(value) {
if (missing(value)) return(private$.match_requests_on)
private$.match_requests_on <- check_request_matchers(value)
},
allow_unused_http_interactions = function(value) {
if (missing(value)) return(private$.allow_unused_http_interactions)
private$.allow_unused_http_interactions <- value
},
serialize_with = function(value) {
if (missing(value)) return(private$.serialize_with)
private$.serialize_with <- value
},
json_pretty = function(value) {
if (missing(value)) return(private$.json_pretty)
private$.json_pretty <- value
},
persist_with = function(value) {
if (missing(value)) return(private$.persist_with)
private$.persist_with <- value
},
ignore_hosts = function(value) {
if (missing(value)) return(private$.ignore_hosts)
private$.ignore_hosts <- assert(value, "character")
},
ignore_localhost = function(value) {
if (missing(value)) return(private$.ignore_localhost)
private$.ignore_localhost <- assert(value, "logical")
},
ignore_request = function(value) {
if (missing(value)) return(private$.ignore_request)
private$.ignore_request <- value
},
uri_parser = function(value) {
if (missing(value)) return(private$.uri_parser)
private$.uri_parser <- value
},
preserve_exact_body_bytes = function(value) {
if (missing(value)) return(private$.preserve_exact_body_bytes)
private$.preserve_exact_body_bytes <- value
},
turned_off = function(value) {
if (missing(value)) return(private$.turned_off)
private$.turned_off <- value
},
re_record_interval = function(value) {
if (missing(value)) return(private$.re_record_interval)
private$.re_record_interval <- value
},
clean_outdated_http_interactions = function(value) {
if (missing(value)) return(private$.clean_outdated_http_interactions)
private$.clean_outdated_http_interactions <- value
},
allow_http_connections_when_no_cassette = function(value) {
if (missing(value)) return(private$.allow_http_connections_when_no_cassette)
private$.allow_http_connections_when_no_cassette <- value
},
cassettes = function(value) {
if (missing(value)) return(private$.cassettes)
private$.cassettes <- value
},
linked_context = function(value) {
if (missing(value)) return(private$.linked_context)
private$.linked_context <- value
},
log = function(value) {
if (missing(value)) return(private$.log)
private$.log <- assert(value, "logical")
},
log_opts = function(value) {
if (missing(value)) return(private$.log_opts)
log_opts <- assert(value, "list")
if (length(log_opts) > 0) {
if ("file" %in% names(log_opts)) {
assert(log_opts$file, "character")
if (private$.log) vcr_log_file(log_opts$file)
}
if ("log_prefix" %in% names(log_opts)) {
assert(log_opts$log_prefix, "character")
}
if ("date" %in% names(log_opts)) {
assert(log_opts$date, "logical")
}
}
# add missing log options
log_opts <- merge_list(
log_opts,
list(file = "vcr.log", log_prefix = "Cassette", date = TRUE)
)
private$.log_opts <- log_opts
},
filter_sensitive_data = function(value) {
if (missing(value)) return(private$.filter_sensitive_data)
private$.filter_sensitive_data <- assert(value, "list")
},
filter_sensitive_data_regex = function(value) {
if (missing(value)) return(private$.filter_sensitive_data_regex)
private$.filter_sensitive_data_regex <- assert(value, "list")
},
filter_request_headers = function(value) {
if (missing(value)) return(private$.filter_request_headers)
if (is.character(value)) value <- as.list(value)
private$.filter_request_headers <- assert(value, "list")
},
filter_response_headers = function(value) {
if (missing(value)) return(private$.filter_response_headers)
if (is.character(value)) value <- as.list(value)
private$.filter_response_headers <- assert(value, "list")
},
filter_query_parameters = function(value) {
if (missing(value)) return(private$.filter_query_parameters)
if (is.character(value)) value <- as.list(value)
lapply(value, function(w) {
if (!length(w) %in% 0:2)
stop("filter query values must be of length 1 or 2",
call. = FALSE)
})
private$.filter_query_parameters <- assert(value, "list")
},
write_disk_path = function(value) {
if (missing(value)) return(private$.write_disk_path)
private$.write_disk_path <- value
},
verbose_errors = function(value) {
env_ve <- vcr_env_verbose_errors()
if (missing(value) && is.null(env_ve)) return(private$.verbose_errors)
value <- env_ve %||% value
private$.verbose_errors <- assert(value, "logical")
},
quiet = function(value) {
if (missing(value)) return(private$.quiet)
private$.quiet <- assert(value, "logical")
},
warn_on_empty_cassette = function(value) {
if (missing(value)) return(private$.warn_on_empty_cassette)
private$.warn_on_empty_cassette <- assert(value, "logical")
}
),
public = list(
initialize = function(
dir = ".",
record = "once",
match_requests_on = c("method", "uri"),
allow_unused_http_interactions = TRUE,
serialize_with = "yaml",
json_pretty = FALSE,
persist_with = "FileSystem",
ignore_hosts = NULL,
ignore_localhost = FALSE,
ignore_request = NULL,
uri_parser = "crul::url_parse",
preserve_exact_body_bytes = FALSE,
turned_off = FALSE,
re_record_interval = NULL,
clean_outdated_http_interactions = FALSE,
allow_http_connections_when_no_cassette = FALSE,
cassettes = list(),
linked_context = NULL,
log = FALSE,
log_opts = list(file = "vcr.log", log_prefix = "Cassette", date = TRUE),
filter_sensitive_data = NULL,
filter_sensitive_data_regex = NULL,
filter_request_headers = NULL,
filter_response_headers = NULL,
filter_query_parameters = NULL,
write_disk_path = NULL,
verbose_errors = FALSE,
quiet = TRUE,
warn_on_empty_cassette = TRUE
) {
self$dir <- dir
self$record <- record
self$match_requests_on <- match_requests_on
self$allow_unused_http_interactions <- allow_unused_http_interactions
self$serialize_with <- serialize_with
self$json_pretty <- json_pretty
self$persist_with <- persist_with
self$ignore_hosts <- ignore_hosts
self$ignore_localhost <- ignore_localhost
self$ignore_request <- ignore_request
self$uri_parser <- uri_parser
self$preserve_exact_body_bytes <- preserve_exact_body_bytes
self$turned_off <- turned_off
self$re_record_interval <- re_record_interval
self$clean_outdated_http_interactions <- clean_outdated_http_interactions
self$allow_http_connections_when_no_cassette <- allow_http_connections_when_no_cassette
self$cassettes <- cassettes
self$linked_context <- linked_context
self$log <- log
self$log_opts <- log_opts
self$filter_sensitive_data <- filter_sensitive_data
self$filter_sensitive_data_regex <- filter_sensitive_data_regex
self$filter_request_headers = filter_request_headers
self$filter_response_headers = filter_response_headers
self$filter_query_parameters = filter_query_parameters
self$write_disk_path <- write_disk_path
self$verbose_errors <- verbose_errors
self$quiet <- quiet
self$warn_on_empty_cassette <- warn_on_empty_cassette
},
# reset all settings to defaults
reset = function() self$initialize(),
# print out names of configurable settings
fields = function() sub("^\\.", "", names(private)),
# return current configuration as a list
as_list = function() {
setNames(mget(names(private), private), self$fields())
},
print = function(...) {
cat("<vcr configuration>", sep = "\n")
cat(paste0(" Cassette Dir: ", private$.dir), sep = "\n")
cat(paste0(" Record: ", private$.record), sep = "\n")
cat(paste0(" Serialize with: ", private$.serialize_with), sep = "\n")
cat(paste0(" URI Parser: ", private$.uri_parser), sep = "\n")
cat(paste0(" Match Requests on: ",
pastec(private$.match_requests_on)), sep = "\n")
cat(paste0(" Preserve Bytes?: ",
private$.preserve_exact_body_bytes), sep = "\n")
logloc <- if (private$.log) sprintf(" (%s)", private$.log_opts$file) else ""
cat(paste0(" Logging?: ", private$.log, logloc), sep = "\n")
cat(paste0(" ignored hosts: ", pastec(private$.ignore_hosts)), sep = "\n")
cat(paste0(" ignore localhost?: ", private$.ignore_localhost), sep = "\n")
cat(paste0(" Write disk path: ", private$.write_disk_path), sep = "\n")
invisible(self)
}
)
)
pastec <- function(x) paste0(x, collapse = ", ")
vcr_env_verbose_errors <- function() {
var <- "VCR_VERBOSE_ERRORS"
x <- Sys.getenv(var, "")
if (x != "") {
x <- as.logical(x)
vcr_env_var_check(x, var)
x
}
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.