1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
|
#' @title RequestHandler
#' @description Base handler for http requests, deciding whether a
#' request is stubbed, to be ignored, recordable, or unhandled
#' @export
#' @details
#' \strong{Private Methods}
#' \describe{
#' \item{\code{request_type(request)}}{
#' Get the request type
#' }
#' \item{\code{externally_stubbed()}}{
#' just returns FALSE
#' }
#' \item{\code{should_ignore()}}{
#' should we ignore the request, depends on request ignorer
#' infrastructure that's not working yet
#' }
#' \item{\code{has_response_stub()}}{
#' Check if there is a matching response stub in the
#' http interaction list
#' }
#' \item{\code{get_stubbed_response()}}{
#' Check for a response and get it
#' }
#' \item{\code{request_summary(request)}}{
#' get a request summary
#' }
#' \item{\code{on_externally_stubbed_request(request)}}{
#' on externally stubbed request do nothing
#' }
#' \item{\code{on_ignored_request(request)}}{
#' on ignored request, do something
#' }
#' \item{\code{on_recordable_request(request)}}{
#' on recordable request, record the request
#' }
#' \item{\code{on_unhandled_request(request)}}{
#' on unhandled request, run UnhandledHTTPRequestError
#' }
#' }
#' @examples \dontrun{
#' # record mode: once
#' vcr_configure(
#' dir = tempdir(),
#' record = "once"
#' )
#'
#' data(crul_request)
#' crul_request$url$handle <- curl::new_handle()
#' crul_request
#' x <- RequestHandler$new(crul_request)
#' # x$handle()
#'
#' # record mode: none
#' vcr_configure(
#' dir = tempdir(),
#' record = "none"
#' )
#' data(crul_request)
#' crul_request$url$handle <- curl::new_handle()
#' crul_request
#' insert_cassette("testing_record_mode_none", record = "none")
#' #file.path(vcr_c$dir, "testing_record_mode_none.yml")
#' x <- RequestHandlerCrul$new(crul_request)
#' # x$handle()
#' crul_request$url$url <- "https://api.crossref.org/works/10.1039/c8sm90002g/"
#' crul_request$url$handle <- curl::new_handle()
#' z <- RequestHandlerCrul$new(crul_request)
#' # z$handle()
#' eject_cassette("testing_record_mode_none")
#' }
RequestHandler <- R6::R6Class(
'RequestHandler',
public = list(
#' @field request_original original, before any modification
request_original = NULL,
#' @field request the request, after any modification
request = NULL,
#' @field vcr_response holds [VcrResponse] object
vcr_response = NULL,
#' @field stubbed_response the stubbed response
stubbed_response = NULL,
#' @field cassette the cassette holder
cassette = NULL,
#' @description Create a new `RequestHandler` object
#' @param request The request from an object of class `HttpInteraction`
#' @return A new `RequestHandler` object
initialize = function(request) {
self$request_original <- request
self$request <- {
Request$new(request$method, request$url$url %||% request$url,
webmockr::pluck_body(request) %||% "", request$headers,
disk = !is.null(request$output$path))
}
self$cassette <- tryCatch(current_cassette(), error = function(e) e)
},
#' @description Handle the request (`request` given in `$initialize()`)
#' @return handles a request, outcomes vary
handle = function() {
vcr_log_info(sprintf("Handling request: %s (disabled: %s)",
private$request_summary(self$request),
private$is_disabled()), vcr_c$log_opts$date)
req_type <- private$request_type()
req_type_fun <- sprintf("private$on_%s_request", req_type)
vcr_log_info(sprintf("Identified request type: (%s) for %s",
req_type,
private$request_summary(self$request)), vcr_c$log_opts$date)
eval(parse(text = req_type_fun))(self$request)
}
),
private = list(
request_summary = function(request) {
request_matchers <- if (
!inherits(self$cassette, c("error", "list")) &&
!is.null(self$cassette)
) {
self$cassette$match_requests_on
} else {
vcr_c$match_requests_on
}
request_summary(Request$new()$from_hash(request), request_matchers)
},
request_type = function() {
if (private$externally_stubbed()) {
# FIXME: not quite sure what externally_stubbed is meant for
# perhaps we can get rid of it here if only applicable in Ruby
# cat("request_type: is externally stubbed", "\n")
"externally_stubbed"
} else if (private$should_ignore(self$request)) {
# cat("request_type: is ignored", "\n")
"ignored"
} else if (private$has_response_stub(self$request)) {
# cat("request_type: is stubbed_by_vcr", "\n")
"stubbed_by_vcr"
} else if (real_http_connections_allowed()) {
# cat("request_type: is recordable", "\n")
"recordable"
} else {
# cat("request_type: is unhandled", "\n")
"unhandled"
}
},
# request type helpers
externally_stubbed = function() FALSE,
should_ignore = function(request) {
request_ignorer$should_be_ignored(request)
},
has_response_stub = function(request) {
hi <- http_interactions()
if (length(hi$interactions) == 0) return(FALSE)
hi$has_interaction_matching(request)
},
is_disabled = function(adapter = "crul") !webmockr::enabled(adapter),
# get stubbed response
get_stubbed_response = function(request) {
self$stubbed_response <- http_interactions()$response_for(request)
self$stubbed_response
},
#####################################################################
### various on* methods, some global for any adapter,
### and some may be specific to an adapter
### - all fxns take `request` param for consistentcy, even if they dont use it
##### so we can "monkey patch" these in each HTTP client adapter by
##### reassigning some of these functions with ones specific to the HTTP client
on_externally_stubbed_request = function(request) NULL,
on_ignored_request = function(request) {
# perform and return REAL http response
# reassign per adapter
},
on_stubbed_by_vcr_request = function(request) {
# return stubbed vcr response - no real response to do
# reassign per adapter
},
on_recordable_request = function(request) {
# do real request - then stub response - then return stubbed vcr response
# - this may need to be called from webmockr cruladapter?
# reassign per adapter
},
on_unhandled_request = function(request) {
err <- UnhandledHTTPRequestError$new(request)
err$run()
}
)
)
|